【问题标题】:Strange behavior of type casting类型转换的奇怪行为
【发布时间】:2014-10-23 04:01:57
【问题描述】:

我正在尝试从程序集中创建某种类型。该类型实现了接口IDerrivedInterface,它继承自接口IBaseInterface。所以,我要创建类型的实例,实现IBaseInterface

if (assembly != null)
{
     ObjTypes = assembly.GetTypes(); 
     foreach (var objType in ObjTypes)
     {
         try
         {
             var type = Activator.CreateInstance(objType);
             if (type is IBaseInterface)
             {
                  list.Add((IBaseInterface) type);                
             }
         }
         catch (Exception ex)
         {
             int a = 0;
         }
     }
}

有类型,在assembly中实现IDerrivedInterface。但是list.Add((IBaseInterface) type)这行代码没有被执行。我试图对此进行调试:我将type is IBaseInterface 添加到“手表”中,该值为True。这种行为的原因是什么?

统一更新: list - 是简单的 List。我觉得没关系。不会抛出异常。 IDerrived接口继承自IBaseInterface

interface IBaseInterface
{
//
}
interface IDerrivedInterface : IBaseInterface
{
}
//and a class in assembly:
class SomeType : IDerrivedInterface
{
}

UPD2: 程序集是从某个文件夹加载的。该文件夹中有几个程序集和几个其他文件。我正在遍历所有带有“.dll”扩展名的文件。然后我将所有类型实现IBaseInterface 的对象收集到列表中。我的类型(实现IBaseInterface)和IBaseInterface 的声明放在不同的程序集中。 因此,如果没有程序集(其中包含 IBaseInterface 的声明),它就可以工作。但是如果有那个程序集(并且它在使用 Type 程序集之前处理过)它就不起作用。

UPD3: 有几个不同的接口实现了该类型。此外,该类型源自一些BaseClass。它应该工作,但它没有..

这是some question 关于另一个错误,但有一个关于在不同上下文中访问两个程序集的问题。也许这是我的情况。因为库(让它成为“L1”)引用了库(L2),其中放置了接口的声明。还有一个库(L3),其中包含类的声明,它实现了 L2 的接口(这就是 L3 也引用 L2 的原因)。所以我在 L1 中调试(它引用了 L2)并加载程序集 L2 和 L3)。也许这就是我遇到这个问题的原因..

【问题讨论】:

  • 您是说它进入了if 块并且没有抛出异常,但list 不包含该类型?
  • 只创建您需要类型的实例,不要创建所有类型的实例并选择您的需要。还发布一些重现问题的代码。目前我们无法判断出了什么问题。
  • 你的list是什么对象?
  • 为什么不在尝试创建它的实例之前检查该类型是否实现了您想要的接口
  • IMO,这里要看的重要一点是:抛出了什么异常?也许在catch 块中记录ex.Message。另外:list 是什么?它是某种简单的列表吗?还是可以做一些自定义的事情,例如:如果是星期五并且月亮在金星,则在请求时不添加项目。

标签: c# interface casting activator


【解决方案1】:

所以我使用构建后事件解决它并仅将 1 个 dll 复制到子文件夹(程序搜索 DLL 的类型)。在此之前,有几个依赖的 DLL,据我所知,它们会给我错误的行为。

【讨论】:

    【解决方案2】:

    程序集将包含三种类型 IBaseInterface、IDerrivedInterface 和一个实现 IDerrivedInterface 的类。线

              var type = Activator.CreateInstance(objType);
    

    将抛出异常,因为您无法创建接口类型的对象。由于接口类型的变量可以保存实现接口的类的对象的引用,但不能是它自己的对象。类的代码

            if (type is IBaseInterface)
             {
                  list.Add((IBaseInterface) type);                
             }
    

    如果列表是IBaseInterface,就会成功执行。

    已编辑:添加代码。

    我创建了一个 ClassLibrary,如下所示。

    namespace ClassLibrary
    {
        public interface IBaseInterface
        {
        }
        public interface IDerivedInterface : IBaseInterface
        {
        }
    
        public class Class1:IDerivedInterface
        {
    
        }
    }
    

    在另一个项目中我执行了以下代码。

            List<IBaseInterface> list = new List<IBaseInterface>();
            var assembly = System.Reflection.Assembly.LoadFrom("ClassLibrary.dll");
            if (assembly != null)
            {
                var ObjTypes = assembly.GetTypes();
                foreach (var objType in ObjTypes)
                {
                    try
                    {
                        var type = Activator.CreateInstance(objType);
                        if (type is IBaseInterface)
                        {
                            list.Add((IBaseInterface)type);
                        }
                    }
                    catch (Exception ex)
                    {
                        int a = 0;
                    }
                }
            }
    

    它为前两个接口抛出异常并为类类型添加了一个项目。

    【讨论】:

    • 是的,我明白了。但是列表中没有项目,尽管该程序集中有实现该接口的类型。
    • @Alexey 我已经根据我的解释编辑了我的解决方案并编写了我能够成功执行的代码。
    • 是的,我刚试过。并将接口和类的声明放置到不同的库中。它工作正常。但在实际项目中它仍然不起作用。这意味着还有更多……我忽略了。比如这个类型不是简单的实现那个接口,它是从另一个类派生出来的,又实现了几个接口。
    【解决方案3】:

    据我了解,问题在于list.Add((IBaseInterface) type); 行没有被执行。

    您确定您的 IDE(我猜是 Visual Studio)设置为 DEBUG 而不是 RELEASE?也许你只是没有看到它被执行。

    也许你在那里有一个异常,你在其他地方捕获了它。如果 if 包含一个 TRUE,那么它必须进入 if 语句中。

    【讨论】:

    • 是DEBUG模式。当它处理实现该接口的我的类型时也不例外。但它没有添加到列表中。虽然,“手表”窗口中的条件为真。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 2011-10-07
    • 2012-10-05
    • 2016-01-14
    • 1970-01-01
    相关资源
    最近更新 更多