将对象转换为泛型T.

时间:2010-07-05 17:42:46

标签: c# .net generics casting

我遇到一些我无法解决的演员阵容有点麻烦。

我有这个界面和以下实现:

public interface IConfigureServiceOnServer
{
    void Configure(Service service);
}

public sealed class ServiceConfigurator : IConfigureServiceOnServer
{
 ...
}

我在运行时使用字典(包含程序集和类型名称)使用以下方法加载这些类型:

 public static T Resolve<T>(string type, params object[] values) where T : class
        {
            var split = refs[type].Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var assembly = Assembly.LoadFrom(split[0] + ".dll");
            var instance = assembly.CreateInstance(
                split[1], // the name of the Type to instantiate
                true,
                BindingFlags.CreateInstance,
                null,
                values, // the params to use in the constructor
                null,
                null);
            T ret = (T)instance; //also tried with 'instance as T'
            return ret;
        }

我这样调用它时会得到一个无效的强制转换异常

Resolver.Resolve<IConfigureServiceOnServer>("serviceconfiguration", "");

我无法弄清楚为什么我会得到这个异常,因为相同的代码适用于下一个接口及其实现:

public interface IServiceManager
{
    void Create();
    void Configure();
}

public sealed class Service : IServiceManager
{
...
}

为什么相同的代码适用于第二个示例而不适用于第一个示例的任何想法?

提前致谢。

编辑:

当我正在调试并且我在Resolve方法返回之前停止执行时我可以使用立即窗口 - 我测试演员并且它有效。

EDIT2: 这是异常消息:

Unable to cast object of type 'Codegarten.Controller.Configuration.Service.ServiceConfigurator' to type 'Codegarten.Controller.Configuration.IConfigureServiceOnServer '.

EDIT3: 更多信息 - 有人建议使用反射加载的类型可能是错误的,所以我做了一些调试。我检查了加载类型是否使用visual studio中的即时窗口实现了所需的界面:

>instance.GetType().GetInterfaces()
{System.Type[1]}
    [0]: {Name = "IConfigureServiceOnServer" FullName = "Codegarten.Controller.Configuration.IConfigureServiceOnServer"}


好的,问题是由Assembly.LoadFrom方法引起的,该方法将程序集加载到与应用程序不同的上下文中。

我使用Assembly.Load解决了这个问题。

2 个答案:

答案 0 :(得分:2)

你绝对确定

中的IConfigureServiceOnServer类型
Resolver.Resolve<IConfigureServiceOnServer>("serviceconfiguration", "");

在同一个程序集中的同一名称空间中编译与类定义中的类型完全相同的类型?

public sealed class ServiceConfigurator : IConfigureServiceOnServer {
    ...
}

我猜你的解决方案中有某种Web服务的名字。可能IConfigureServiceOnServer在一个位置引用服务中定义的实际接口,而另一个位置的IConfigureServiceOnServer引用服务引用中定义的代理副本?

或者,ServiceConfigurator类可能编译为与反射代码中实际实例化的类型不同的类型。

<强>更新

我建议您调试类及其接口的AssemblyQualifiedName属性,以获取(a)原始定义的类型,以及(b)通过反射实例化的属性。

答案 1 :(得分:1)

我怀疑您遇到的问题是类型被加载到不同的上下文中。使用Assembly.LoadFrom会将类型加载到LoadFrom上下文中,而您定义的接口我猜是在Load上下文中。有关LoadFrom上下文的详细信息,请参阅此处。

您是否从不同位置加载程序集?如果不是,您可以尝试使用Assembly.Load使用显示名称加载程序集,这应该将类型加载到与接口相同的上下文中,并且您的转换应该可以工作,因为类型标识有望匹配。如果这样做,您可能最好只使用程序集限定名称并使用Type.GetType加载类型。