wcf公开泛型
我有一个客户端和服务器共享类型的应用程序,互操作性不是我们关心的问题之一。我计划为所有支持web的对象建立一个单一的存储库,并且我正在考虑为我公开的服务提供一个通用接口 类似于T GetObject(intid) 但是wcf不喜欢它,因为它试图公开它的模式(我并不真正关心)wcf公开泛型,wcf,generics,wcf-binding,Wcf,Generics,Wcf Binding,我有一个客户端和服务器共享类型的应用程序,互操作性不是我们关心的问题之一。我计划为所有支持web的对象建立一个单一的存储库,并且我正在考虑为我公开的服务提供一个通用接口 类似于T GetObject(intid) 但是wcf不喜欢它,因为它试图公开它的模式(我并不真正关心) 有可能用WCF做这样的事情吗?我可以使用任何类型的绑定不必是httpbinding或wsbinding…不,你不能。无论您是否需要或需要互操作性,WCF的最基本的基础是消息交换。 客户端向服务器发送消息并返回响应。该消息是客
有可能用WCF做这样的事情吗?我可以使用任何类型的绑定不必是httpbinding或wsbinding…不,你不能。无论您是否需要或需要互操作性,WCF的最基本的基础是消息交换。 客户端向服务器发送消息并返回响应。该消息是客户端和服务器之间传递的所有消息,需要序列化为XML或二进制格式。这就是为什么传递的任何数据都必须是原子的(如int、string)或DataContract,这是WCF服务堆栈关于如何序列化和反序列化此类对象的描述 您不能传递任何接口或其他“诡计”——客户端和服务器之间的所有内容基本上都必须能够在XML模式中表达 所以我担心你想要达到的目标与WCF提供的完全相反。SOA(面向服务的应用程序)的世界和范例是完全不同的,并不总是与OOP的思想和机制100%同步
马克我想这是可能的,尽管我不确定你会想要这个。我会采用以下方法(未经测试,不确定是否有效)。首先在解决方案中创建以下项目结构:
ServiceInterfaces
(参考服务实现
和服务接口
)模型类
ModelClasses
(参考主机
和服务接口
)服务实现
(参考客户端
和服务接口
)模型类
ServiceInterfaces
中,您有这样一个接口(我跳过了名称空间等,以缩短示例):
在Host
中,您在App.config
(或Web.config
)文件中为您的服务提供了正确的配置,并使用以下代码托管您的服务(假设它是一个独立的应用程序):
最后,在Client
中,您使用一个类来定义代理:
Binding binding = new BasicHttpBinding(); // For the example, could be another binding.
EndpointAddress address = new EndpointAddress("http://localhost:8000/......");
IMyService<string> myService =
ChannelFactory<IMyService<string>>.CreateChannel(binding, address);
string myObject = myService.GetObject(42);
Binding Binding=new BasicHttpBinding();//例如,可以是另一个绑定。
EndpointAddress地址=新的EndpointAddress(“http://localhost:8000/......");
IMyService myService=
CreateChannel(绑定,地址);
字符串myObject=myService.GetObject(42);
同样,我不确定这是否有效。诀窍是在主机和客户端之间共享服务接口(在
ServiceInterfaces
中)和域模型对象(在ModelClasses
)。在我的示例中,我使用一个字符串从服务方法返回,但它可以是ModelClasses
项目中的任何数据协定类型。如果使用ServiceKnownTypesDiscovery,您可以这样做
例如:
[ServiceKnownType("GetKnownTypes", typeof(ServiceKnownTypesDiscovery))]
public interface ISomeService
{
[OperationContract]
object Request(IRequestBase parameters);
}
GetKnownTypes可以这样声明:
public static class ServiceKnownTypesDiscovery
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new List<Type>();
foreach (var asmFile in Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, "*.dll"))
{
Assembly asm = Assembly.LoadFrom(asmFile);
types.AddRange(asm.GetTypes().Where(p=> Attribute.IsDefined(p,typeof(DataContractAttribute))));
}
return types;
}
}
公共静态类ServiceKnownTypesDiscovery
{
公共静态IEnumerable GetKnownTypes(ICustomAttributeProvider提供程序)
{
变量类型=新列表();
foreach(目录.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath??AppDomain.CurrentDomain.BaseDirectory,“*.dll”)中的var asmFile)
{
Assembly asm=Assembly.LoadFrom(asmFile);
types.AddRange(asm.GetTypes().Where(p=>Attribute.IsDefined(p,typeof(DataContractAttribute)));
}
返回类型;
}
}
在这种情况下,使用[DataContract]声明的所有内容(只要它们在服务器和客户端都可以发现)都可以序列化
我希望这有帮助 按照前面的示例,您可以声明一个对象为
DataMember
的DataContract
。然后,您可以添加一个扩展方法来获取和设置对象数据成员的泛型类型。您也可以将其设置为内部,这样您就必须使用扩展方法来获取和设置值
当然,只有使用svcuti
(或VisualStudio)生成客户机并使用extensions方法引用包含数据协定和类的程序集时,它才起作用
希望这有帮助……所以如果有人想这样做,微软提供了什么技术堆栈,它更适合远程处理(如果它仍然存在的话)?Ms确实扩展了对共享类型(netcontractserializer等)的支持。我不知道目前是否有任何远程处理对象的解决方案—这基本上就是您正在尝试的。这种方法确实存在一些问题,微软试图用WCF来解决这些问题,但为了解决这些问题,我们必须使用完全基于消息的模型,这种模型在接口和泛型中不起作用。是的,它支持共享具体类型,但绝对不支持接口,也不支持真正的泛型。我可以在客户端引用相同的程序集,并使用服务引用UTILY(我猜是svcutil)的advance选项卡来共享类型,这是可行的,但现在我想做的是抽象的,我想我正在寻找remotint类型解决方案,但在wcf上应该是可能的…我的方法不应该使用Visual Studio中的“添加服务引用”对话框。那是行不通的。这就是我使用ChannelFactory类的原因。它会动态生成服务接口的代理实现,而不需要元数据。这很可能不起作用(我现在无法测试),因为您使用返回泛型类型“t”的操作定义服务,但为了正常工作,该类型“t”必须是DataContract,以便WCF堆栈可以序列化和反序列化该对象
Binding binding = new BasicHttpBinding(); // For the example, could be another binding.
EndpointAddress address = new EndpointAddress("http://localhost:8000/......");
IMyService<string> myService =
ChannelFactory<IMyService<string>>.CreateChannel(binding, address);
string myObject = myService.GetObject(42);
[ServiceKnownType("GetKnownTypes", typeof(ServiceKnownTypesDiscovery))]
public interface ISomeService
{
[OperationContract]
object Request(IRequestBase parameters);
}
public static class ServiceKnownTypesDiscovery
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
var types = new List<Type>();
foreach (var asmFile in Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, "*.dll"))
{
Assembly asm = Assembly.LoadFrom(asmFile);
types.AddRange(asm.GetTypes().Where(p=> Attribute.IsDefined(p,typeof(DataContractAttribute))));
}
return types;
}
}