【问题标题】:How to convert object to specific class with using type information如何使用类型信息将对象转换为特定类
【发布时间】:2022-12-05 15:57:47
【问题描述】:

我有一个界面。该接口名称是 IQueue。我也有具体的课程。它们的名称是 MyMessage1 和 MyMessage2。

public interface IQueue 
{
}

public class MyMessage1 : IQueue 
{
    public string Message { get; set; }
    public DateTime PublishedDate { get; set; }
}

public class MyMessage2 : IQueue 
{
    public string Name { get; set; }
}

我正在通过反射从 IQueue 获取所有具体类并创建一个实例。

var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => typeof(IQueue).IsAssignableFrom(p) && p.IsClass)
    .ToList);

foreach(var type in types) 
{
    var instance = Activator.CreateInstance(type);
}

实例是一个对象。如何在不使用以下代码的情况下转换为特定类?可能吗。

(MyMessage1)Activator.CreateInstance(type)
(MyMessage2)Activator.CreateInstance(type)

我想使用类型信息创建一个特定的类实例

【问题讨论】:

  • 如果您已经知道具体类型 - 为什么不直接使用 new MyMessage1()

标签: c# .net


【解决方案1】:

强制转换为 IQueue 类型,因为您要实例化的所有类型都实现了该接口。

IQueue instance = (IQueue)Activator.CreateInstance(type);

将要使用的方法和属性添加到该接口。具体类将必须实现这些方法和属性,您可以通过接口访问它们。

【讨论】:

    【解决方案2】:

    复制下面的代码 sn-p 并粘贴到您的班级中

    internal static void Register(Type interfaceType)
            {
                var interfaceTypes =
                    AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(s => s.GetTypes())
                        .Where(t => interfaceType.IsAssignableFrom(t)
                                    && t.IsClass && !t.IsAbstract)
                        .Select(t => new
                        {
                            parentInterface = t.GetInterfaces().FirstOrDefault(),
                            Implementation = t
                        })
                        .Where(t => t.parentInterface is not null
                                    && interfaceType.IsAssignableFrom(t.parentInterface));
    
                foreach (var type in interfaceTypes)
                {
                    var instance = Activator.CreateInstance(type.Implementation);
    
                }
            }
    

    AddServices(typeof(IQueue));一样使用

    【讨论】:

    • 你能解释一下吗?目前,创建的对象没有存储在任何地方,也无法从外部访问。
    • 您需要一个实例或多个实例
    【解决方案3】:

    是的,可以使用反射将类的实例转换为特定类型。你可以使用类型.IsAssignableFrom方法来检查类的实例是否可以分配给特定类型的变量。如果可以将实例分配给类型,则可以使用转换.ChangeType将实例转换为特定类型的方法。

    这是您如何执行此操作的示例:

    foreach(var type in types) 
    {
        var instance = Activator.CreateInstance(type);
    
        if (typeof(MyMessage1).IsAssignableFrom(instance.GetType()))
        {
            var message1 = (MyMessage1)Convert.ChangeType(instance, typeof(MyMessage1));
            // Use message1 here
        }
        else if (typeof(MyMessage2).IsAssignableFrom(instance.GetType()))
        {
            var message2 = (MyMessage2)Convert.ChangeType(instance, typeof(MyMessage2));
            // Use message2 here
        }
    }
    

    或者,您可以使用作为运算符将实例转换为特定类型,这将返回无效的如果实例无法转换为指定类型:

    foreach(var type in types) 
    {
        var instance = Activator.CreateInstance(type);
    
        var message1 = instance as MyMessage1;
        if (message1 != null)
        {
            // Use message1 here
        }
    
        var message2 = instance as MyMessage2;
        if (message2 != null)
        {
            // Use message2 here
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-21
      • 2019-04-10
      • 2015-01-01
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多