【问题标题】:DotNet: Is it possibly cast dynamic to interface typeDotNet:是否可能将动态转换为接口类型
【发布时间】:2022-01-02 18:11:42
【问题描述】:

我有一个包含一些业务逻辑的外部 DLL。 我想做这样的事情:

  1. 在运行时加载 DLL
  2. 按某些标准过滤可用类型。
  3. 创建目标类型实例 即动态 c = Activator.CreateInstance(type);
  4. 将先前创建的实例转换为某个接口以将其传递给处理程序方法

所以外部 dll 将包含类似的内容:

namespace External.Handler.Namespace
{
    using System;

    public interface IHandler {
        int Process(string arg);
        int ProcessV2(string arg);
    }

    public class HandlerImpl : IHandler
    {
        public int Process(string arg)
        {
            // ... implementation
            return 0;
        }

        public int ProcessV2(string arg)
        {
            // ... implementation
            return 0;
        }
    }
}

在目标服务我想加载它并尝试转换到内部接口

namespace My.Target.Namespace
{
    using System;
    using System.Reflection;

    public interface IInternalHandler {
        int Process(string arg)
    }

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"path\to\dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                 dynamic c = Activator.CreateInstance(type);
                 try 
                 {
                     // I would like to know: how perform it?
                     var typedInstance = (IInternalInterface) c;
                     Handle(typedInstance);
                 }
                 catch {}
            }

            Console.ReadLine();
        }

        public static void Handle(IInternalHandler handler, string arg) {
            int result = handler.Process(arg);
            Console.log(result);
        }
    }
}

总结:是否可以将dynamic 转换为部分匹配的接口?

【问题讨论】:

  • 你试过了吗:IInternalInterface c = Activator.CreateInstance(type);
  • @PoulBak 是的,我得到了例外Unable to cast object of type 'ExternalHandlerNamespace.HandlerImpl' to type 'MyTargetNamespace.IInternalHandler'.

标签: c# .net dynamic dllimport system.reflection


【解决方案1】:

您的HandlerImpl 类没有实现IInternalHandler,因此您不能将其转换为该接口。

您需要将dynamic 实例包装在一个确实实现该接口的类中。例如:

internal class InternalHandlerWrapper : IInternalHandler
{
    private readonly object _handler;
    
    public InternalHandlerWrapper(object handler)
    {
        _handler = handler;
    }
    
    public int Process(string arg)
    {
        dynamic handler = _handler;
        handler.Process(arg);
    }
}

用法:

foreach(Type type in DLL.GetExportedTypes())
{
    if (type.IsAbstract || type.IsInterface) continue;
    
    try 
    {
        object c = Activator.CreateInstance(type);
        var typedInstance = new InternalHandlerWrapper(c);
        Handle(typedInstance);
    }
    catch {}
}

注意:GetExportedTypes 也将返回IHandler 接口本身。如果你将该类型传递给Activator.CreateInstance,你会得到一个异常。您需要从循环中过滤掉抽象和接口类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多