通过在运行时确定类型来创建WCF服务

时间:2013-02-19 20:09:43

标签: wcf service runtime

我试图在运行时不知道其类型/接口的情况下创建WCF服务。为此,我使用ChannelFactory。 ChannelFactory是一个泛型类,所以我需要使用Type.MakeGenericType。传递给MakeGenericType的类型来自我之前通过搜索某些程序集而使用反射收集的接口列表。

最后,我调用MethodInfo.Invoke来创建对象。该对象创建得很好,但我无法将其转换为正确的接口。在投射时,我收到以下错误:

“无法将透明代理转换为输入'Tssc.Services.MyType.IMyType'”

经过一些实验,我发现传递给MakeGenericType的接口/类型似乎是个问题。如果我用我的实际界面替换列表中的界面,那么一切正常。我梳理了两个物体,看不出有什么区别。当我修改代码以生成两种类型时,将它们与Equals进行比较将返回false。我不清楚Equals是否只是检查它们是指同一个对象(不是),还是检查所有属性等等。

这是否与我收集界面的方式有关(反思,保存在列表中......)?对象的比较似乎表明它们是等价的。我打印了两个对象的所有属性,它们是相同的。我需要深入挖掘吗?如果是这样,进入哪里?

         // createService() method

     //*** tried both of these interfaces, only 2nd works - but they seem to be identical
     //Type t = interfaces[i]; // get type from list created above - doesn't work
     Type t = typeof(Tssc.Services.MyType.IMyType); // actual type - works OK

     // create ChannelFactory type with my type parameter (t)
     Type factoryType = typeof(ChannelFactory<>);
     factoryType = factoryType.MakeGenericType(new Type[] { t });         

     // create ChannelFactory<> object with two-param ctor
     BasicHttpBinding binding = new BasicHttpBinding();
     string address = "blah blah blah";
     var factory = Activator.CreateInstance(factoryType, new object[] { binding, address });

     // get overload of ChannelFactory<>.CreateChannel with no parameters
     MethodInfo method = factoryType.GetMethod("CreateChannel", new Type[] { });

     return method.Invoke(factory, null);

     //--------------- code that calls code above and uses its return

     object ob = createService();

     //*** this cast fails
     Tssc.Services.MyType.IMyType service = (Tssc.Services.MyType.IMyType)ob;

1 个答案:

答案 0 :(得分:0)

好的,我理解这里发生了什么 - 问题与加载相同的程序集有效加载两次有关 - 一次是通过引用,一次是通过程序集加载命令。您需要做的是更改加载程序集的位置,并检查当前AppDomain中是否已存在,如下所示:

Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals("ClassLibrary1Name"));

if (assembly == null)
{
    assembly = System.Reflection.Assembly.LoadFile("path to your assembly");
}

//do your work here

这样,如果程序集已经加载到内存中,它将使用那个。