在开展工作时,我们开发了一个可以从外部访问的SOAP WCF API。由于API的一个要求已经改变,我想为此API添加一个新类,以便为某些函数调用生成正确的路径。
我们的API分为3个单独的库:
客户端使用脚本获得前两个服务器,服务器有三个。
我希望添加到API的类看起来像这样:
namespace TenForce.Execution.API.Objects.Helpers
{
/// <summary>
/// <para>This interface defines the functionality available in the PathHelper for the API.</para>
/// </summary>
public interface IPathHelper
{
string ApplicationFolder { get; } // The HomeDataFolder for the application
string CompanyHomeFolder { get; } // The HomeDataFolder for the company.
string CustomFolder { get; } // The custom folder for professional services.
string WikiFolder { get; } // The WIKI folder to store pages.
string AddinsFolder { get; } // The AddinFolder to access the addins.
}
}
实际的类实现看起来像这样:
using System.IO;
using System.Runtime.Serialization;
using TenForce.Execution.BUL;
using TenForce.Execution.Framework;
namespace TenForce.Execution.API.Implementation.Helpers
{
/// <summary>
/// <para>This class provides a direct implementation of the IPathHelper for the API implementation
/// and manages all the paths inside the DataHomeFolder structure for the TenForce application.</para>
/// </summary>
[DataContract]
public class PathHelper : Objects.Helpers.IPathHelper
{
#region Private Fields
private readonly ParameterBUL _mParameterBul;
private const Parameter.ParameterId DataHomeFolderId = Parameter.ParameterId.DataHomeFolder;
private const Parameter.ParameterId CompanyNameId = Parameter.ParameterId.CompanyName;
#endregion
#region Constructor
/// <summary>
/// <para>Creates a new instance of the PathHelper class</para>
/// </summary>
public PathHelper()
{
_mParameterBul = new ParameterBUL();
}
#endregion
#region IPathHelper Members
/// <summary>
/// <para>Returns the absolute path to the DataHomeFolder of the TenForce Application.</para>
/// </summary>
[DataMember]
public string ApplicationFolder
{
get
{
return CreatePath(_mParameterBul.GetParameterValue(DataHomeFolderId));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company DataHomeFolder.</para>
/// </summary>
[DataMember]
public string CompanyHomeFolder
{
get
{
return CreatePath(Path.Combine(ApplicationFolder, _mParameterBul.GetParameterValue(CompanyNameId)));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company custom folder.</para>
/// </summary>
[DataMember]
public string CustomFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"custom"));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company wiki folder.</para>
/// </summary>
[DataMember]
public string WikiFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"wiki"));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company addins folder.</para>
/// </summary>
[DataMember]
public string AddinsFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"addins"));
}
}
#endregion
#region Private Members
/// <summary>
/// <para>Checks if the specified path exists, and creates the path
/// if the system cannot find it.</para>
/// </summary>
/// <param name="path">The path to verify.</param>
private static string CreatePath(string path)
{
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return path;
}
#endregion
}
}
所有这些都是非常基本的东西。 WCF服务是由我们使用.NET提供的工厂和类动态创建的。 WCF服务完全适用于服务中已存在的所有代码。
所以我决定在我们的服务类中添加以下行:
/// <summary>
/// <para>Returns the PathHelper to construct the various paths for API Scripts.</para>
/// </summary>
/// <returns>An instance of the PathHelper.</returns>
public Objects.Helpers.IPathHelper GetPathHelper()
{
return new Helpers.PathHelper();
}
#endregion
当我运行单元测试时,除了那些检查PathHelper功能的测试外,所有测试都有效,它们都会出现相同的错误消息/异常:
错误1 TestCase'TenForce.Execution.API.ImplementationTest / HelperTests / CheckApplicationFolderPath'失败: 执行 System.ServiceModel.CommunicationException:远程端点不再识别此序列。这很可能是由于远程端点中止。 wsrm:Identifier的值不是已知的Sequence标识符。可靠的会议出了问题。
服务器堆栈跟踪: 在System.ServiceModel.Channels.ReliableRequestSessionChannel.SyncRequest.WaitForReply(TimeSpan超时) 在System.ServiceModel.Channels.RequestChannel.Request(消息消息,TimeSpan超时) 在System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息消息,TimeSpan超时) 在System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,Object [] outs,TimeSpan timeout) 在System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,Object [] outs) 在System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作) 在System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
在[0]处重新抛出异常: 在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg) 在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&amp; msgData,Int32 type) 在TenForce.Execution.API.Contracts.IAPI.GetPathHelper() at TenForce.Execution.API.ServiceClient.ServiceAPI.GetPathHelper()in c:\ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ServiceClient \ ServiceAPI.cs:line 163 at TenForce.Execution.API.ImplementationTest.HelperTests.CheckApplicationFolderPath()在C:\ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ImplementationTest \ HelperTests.cs:第56行c:\ Users \ arne.de.herdt \ Documents \ Trunk \ Robinson \ TenForce.Execution.API.ServiceClient \ ServiceAPI.cs 163
我不知道出了什么问题,或者我错过了什么。代码正在为已有的代码工作,但是当我添加我的文章时,它会变得混乱,但现有的功能仍在继续。它是我的,导致问题。
答案 0 :(得分:1)
这个错误对我来说似乎很奇怪,也许它与您动态生成服务的方式有关。
但是,该类不可序列化,该类的属性是只读的(没有set访问器)。要将属性标记为DataMember,属性需要具有set访问者,即使它被标记为私有。来自MSDN:
请注意 已应用DataMemberAttribute属性的属性必须同时包含get和set字段;它们不能只获取或仅设置。
您可能希望在该类中序列化的唯一内容是m_ParameterBul变量,因此将其标记为DataMember并从readonly属性中删除所有其他DataMember属性即可。
您应该注意,如果m_ParameterBul不依赖于服务器,则不需要在服务器端创建此类,因为所有内容都与客户端相关。在这种情况下,您应该直接在客户端上创建它。
希望它有所帮助!
/// <summary>
/// <para>This class provides a direct implementation of the IPathHelper for the API implementation
/// and manages all the paths inside the DataHomeFolder structure for the TenForce application.</para>
/// </summary>
[DataContract]
public class PathHelper : Objects.Helpers.IPathHelper
{
#region Private Fields
[DataMember]
private readonly ParameterBUL _mParameterBul;
private const Parameter.ParameterId DataHomeFolderId = Parameter.ParameterId.DataHomeFolder;
private const Parameter.ParameterId CompanyNameId = Parameter.ParameterId.CompanyName;
#endregion
#region Constructor
/// <summary>
/// <para>Creates a new instance of the PathHelper class</para>
/// </summary>
public PathHelper()
{
_mParameterBul = new ParameterBUL();
}
#endregion
#region IPathHelper Members
/// <summary>
/// <para>Returns the absolute path to the DataHomeFolder of the TenForce Application.</para>
/// </summary>
public string ApplicationFolder
{
get
{
return CreatePath(_mParameterBul.GetParameterValue(DataHomeFolderId));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company DataHomeFolder.</para>
/// </summary>
public string CompanyHomeFolder
{
get
{
return CreatePath(Path.Combine(ApplicationFolder, _mParameterBul.GetParameterValue(CompanyNameId)));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company custom folder.</para>
/// </summary>
public string CustomFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"custom"));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company wiki folder.</para>
/// </summary>
public string WikiFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"wiki"));
}
}
/// <summary>
/// <para>Returns the absolute path to the Company addins folder.</para>
/// </summary>
public string AddinsFolder
{
get
{
return CreatePath(Path.Combine(CompanyHomeFolder, @"addins"));
}
}
#endregion
#region Private Members
/// <summary>
/// <para>Checks if the specified path exists, and creates the path
/// if the system cannot find it.</para>
/// </summary>
/// <param name="path">The path to verify.</param>
private static string CreatePath(string path)
{
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return path;
}
#endregion
}
答案 1 :(得分:0)
感谢评论和awnser的反馈,解决方案是将类移动到第二个API实现,而不是通过WCF服务使其可用。
该类包含函数和只读属性,因此WCF服务无法对类进行序列化。最终的结果是只有脚本可以使用它,而不是服务。