手动编码的 WCF 客户端中不存在 ServiceKnownTypeAttribute
ServiceKnownTypeAttribute does not exist in manually coded WCF client
我正在制作自定义 WCF 客户端,我想在应用程序启动时动态注册 classes。
我在客户端界面上使用属性 ServiceKnownType
:
[ServiceContract(Namespace = "http://example.com/schema/commandservice/v1.0", ConfigurationName = "WcfProxies.IVotesCommandService")]
[ServiceKnownType("GetKnownTypes")]
public interface IVotesCommandService
{
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
void Execute(object command);
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
Task ExecuteAsync(object command);
}
}
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
public VotesCommandServiceClient()
{
}
public VotesCommandServiceClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(Binding binding, EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public void Execute(object command)
{
Channel.Execute(command);
}
public Task ExecuteAsync(object command)
{
return Channel.ExecuteAsync(command);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
// collect and pass back the list of known types
}
}
但是当我尝试使用 class 时它抛出异常:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll. Additional information: ServiceKnownTypeAttribute in MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService refers to a method GetKnownTypes that does not exist in type MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService
但是如果我在下面声明一个外部类型的解析器:
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface IVotesCommandService
.... snip...
static class Helper
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
然后就可以了?!
我还尝试在代理 class 实现上设置 ServiceKnownType
,如下所示:
[ServiceKnownType("GetKnownTypes")]
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
... snip ...
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
但是实际的 GetKnownTypes
函数永远不会被调用,代理在尝试使用它时会爆炸,因为它不知道正在发送的合同。
请问我做错了什么,为什么不调用 class 中的静态 GetKnownTypes 函数?
MSDN documentation 对于您正在使用的构造函数重载说:
Use this constructor when applying the ServiceKnownTypeAttribute to a class that contains methods that return known types.
它在定义属性的类型(IVotesCommandService
)上寻找"GetMethodNames",而不是在运行时间类型(VotesCommandServiceClient
)上寻找。
您需要定义为 [ServiceKnownType("GetKnownTypes", typeof(VotesCommandServiceClient)]
。
我正在制作自定义 WCF 客户端,我想在应用程序启动时动态注册 classes。
我在客户端界面上使用属性 ServiceKnownType
:
[ServiceContract(Namespace = "http://example.com/schema/commandservice/v1.0", ConfigurationName = "WcfProxies.IVotesCommandService")]
[ServiceKnownType("GetKnownTypes")]
public interface IVotesCommandService
{
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
void Execute(object command);
[OperationContract(Action = "http://example.com/schema/commandservice/v1.0/VotesCommandService/Execute", ReplyAction = "http://example.com/schema/commandservice/v1.0/VotesCommandService/ExecuteResponse")]
Task ExecuteAsync(object command);
}
}
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
public VotesCommandServiceClient()
{
}
public VotesCommandServiceClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public VotesCommandServiceClient(Binding binding, EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public void Execute(object command)
{
Channel.Execute(command);
}
public Task ExecuteAsync(object command)
{
return Channel.ExecuteAsync(command);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
// collect and pass back the list of known types
}
}
但是当我尝试使用 class 时它抛出异常:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll. Additional information: ServiceKnownTypeAttribute in MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService refers to a method GetKnownTypes that does not exist in type MyApp.Votes.WinSvc.Test.WcfProxies.IVotesCommandService
但是如果我在下面声明一个外部类型的解析器:
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface IVotesCommandService
.... snip...
static class Helper
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
然后就可以了?!
我还尝试在代理 class 实现上设置 ServiceKnownType
,如下所示:
[ServiceKnownType("GetKnownTypes")]
public class VotesCommandServiceClient : ClientBase<IVotesCommandService>, IVotesCommandService
{
... snip ...
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new[]
{
typeof (UserVotedOnTopicCommand)
};
return types;
}
}
但是实际的 GetKnownTypes
函数永远不会被调用,代理在尝试使用它时会爆炸,因为它不知道正在发送的合同。
请问我做错了什么,为什么不调用 class 中的静态 GetKnownTypes 函数?
MSDN documentation 对于您正在使用的构造函数重载说:
Use this constructor when applying the ServiceKnownTypeAttribute to a class that contains methods that return known types.
它在定义属性的类型(IVotesCommandService
)上寻找"GetMethodNames",而不是在运行时间类型(VotesCommandServiceClient
)上寻找。
您需要定义为 [ServiceKnownType("GetKnownTypes", typeof(VotesCommandServiceClient)]
。