wcf暴露泛型

时间:2009-08-31 19:39:29

标签: wcf generics wcf-binding

我有一个客户端和服务器共享类型的应用程序,互操作性不是我们关注的问题之一。我计划为所有支持Web的对象提供一个存储库,我正在考虑为我的公开服务提供通用接口。

类似T GetObject(int id)

但是wcf不喜欢它,因为它试图暴露它的架构(我真的不关心)

是否可以使用WCF做这样的事情?,我可以使用任何类型的绑定不必是httpbinding或wsbinding ...

4 个答案:

答案 0 :(得分:8)

不,你不能。无论您是否想要或需要互操作性,WCF最基本的基础是消息交换。

客户端向服务器发送消息并获取响应。该消息是客户端和服务器之间传递的所有消息,需要可序列化为XML或二进制格式。这就是为什么传递的任何数据必须是原子的(如int,string)或DataContract - WCF服务堆栈的描述,关于如何序列化和反序列化这些对象。

你不能传递任何接口或其他“技巧” - 客户端和服务器之间的所有内容必须在XML模式中表达,基本上。

所以我担心你想要达到的目标与WCF提供的完全相反。 SOA(面向服务的应用程序)的世界和范例是完全不同的,并不总是100%与OOP的想法和机制同步。

马克

答案 1 :(得分:2)

我想这是可能的,虽然我不确定你是否想要这个。我采取以下方法(未经测试,不确定它是否有效)。首先在解决方案中创建以下项目结构:

  • ServiceInterfaces
  • ServiceImplementations(参考ServiceInterfacesModelClasses
  • ModelClasses
  • Host(参考ServiceInterfacesServiceImplementations
  • Client(参考ServiceInterfacesModelClasses

ServiceInterfaces中,你有一个这样的界面(我跳过命名空间等,以缩短示例):

[ServiceContract]
public interface IMyService<T>
{
    T GetObject(int id);
}

ServiceImplementations中,您有一个实现IMyService<T>的类:

public class MyService<T> : IMyService<T>
{
    T GetObject(int id)
    {
        // Create something of type T and return it. Rather difficult
        // since you only know the type at runtime.
    }
}

Host中,您可以在App.config(或Web.config)文件中使用正确的服务配置,并使用以下代码来托管您的服务(因为它是独立的应用):

ServiceHost host = new ServiceHost(typeof(MessageManager.MessageManagerService))
host.Open();

最后在Client中,您使用ChannelFactory<TChannel>类来定义代理:

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);

同样,我不确定这是否有效。诀窍是在主机和客户端之间共享服务接口(在ServiceInterfaces)和域模型对象(在ModelClasses中)。在我的示例中,我使用字符串从服务方法返回,但它可以是ModelClasses项目中的任何数据协定类型。

答案 2 :(得分:0)

如果您使用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;
    }
}

在这种情况下,使用[DataContract]声明的所有内容(只要它们在服务器和客户端都可以发现)都可以序列化。

我希望这有帮助!

答案 3 :(得分:0)

按照上一个示例,您可以声明DataContract,其对象为DataMember。然后,您可以添加扩展方法以在对象数据成员上获取和设置泛型类型。您也可以将其设为内部,这样您就不得不使用扩展方法来获取和设置值。

当然,只有在使用svcutil(或Visual Studio)生成客户端并且引用包含数据协定的程序集和带扩展方法的类时,它才有效。

希望这会有所帮助......