使用枚举来选择要实例化的类

Rob*_*ert 7 c# abstraction

我有一个我想尝试与dto联系的枚举:

 public enum DtoSelection
 {
     dto1,
     dto2,
     dto3,
 }
Run Code Online (Sandbox Code Playgroud)

此枚举中有108个和值.

我为这些dto中的每一个都有一个dto对象:

 public class dto1 : AbstractDto
 {
       public int Id { get; set; }
       //some stuff specific to this dto
 }
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个方法(最终是一个服务),它将返回一个与所讨论的dto相关联的类型的新dto对象:

 private AbstractDto(int id)
 {
      if (id == DtoSelection.Dto1.ToInt()) //extension method I wrote for enums
            return new Dto1();
      if (id == DtoSelection.Dto2.ToInt())
            return new Dto2();
 }
Run Code Online (Sandbox Code Playgroud)

显然我不想这样做108次.无论出于何种原因,我的大脑只是遗漏了一些明显 处理这个问题的最佳方法是什么.

Hab*_*bib 5

使用Activator.CreateInstance方法并向其传递枚举的ToString值。

Type type = Type.GetType(DtoSelection.dto1.ToString());
var temp = Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)


Tre*_*ley 5

只要在与AbstractDto相同的名称空间中定义了Dto类,该类就可以满足您的要求(如果没有,则需要对其进行调整):

给定以下枚举和类:

public enum DtoSelection
{
    Dto1,
    Dto2,
    Dto3,
}

public abstract class AbstractDto
{
}

public class Dto1 : AbstractDto
{
}

public class Dto2 : AbstractDto
{
}

public class Dto3 : AbstractDto
{
}
Run Code Online (Sandbox Code Playgroud)

此方法将解决它们:

public static class DtoFactory
{
    public static AbstractDto Create(DtoSelection dtoSelection)
    {
        var type = Type.GetType(typeof(AbstractDto).Namespace + "." + dtoSelection.ToString(), throwOnError: false);

        if (type == null)
        {
            throw new InvalidOperationException(dtoSelection.ToString() + " is not a known dto type");
        }

        if (!typeof(AbstractDto).IsAssignableFrom(type))
        {
            throw new InvalidOperationException(type.Name + " does not inherit from AbstractDto");
        }

        return (AbstractDto)Activator.CreateInstance(type);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mau*_*tti 2

解决此问题的一种优雅方法是使用属性和一个基类。我来给你展示:

  1. 您必须创建一个基类。在您的示例中,可能是 AbstractDto,如下所示:

     public abstract class AbstractDto : Attribute
     {
          //code of AbstractDto       
     }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后,我们需要创建一个自定义属性,该属性将在每个 Dto 类上使用,以确定哪个枚举对应于每个类。

     public class DtoEnumAttribute : Attribute
     {
         public DtoSelection Enum { get; set; }
    
         public DtoEnumAttribute(DtoSelection enum)
         {
             this.Enum = enum;
         }
      }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 然后我们应该用适当的枚举来装饰每个子 Dto。我们以 Dto1 为例:

     [DtoEnum(DtoSelection.Dto1)]
     public class Dto1 : AbstractDto
     {
          //code of Dto1
     }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,您可以使用可以接收特定枚举和过滤器或您需要的任何逻辑的方法。以下代码将实例化从AbstractDto继承的每个类,并按您定义的 Enum 排序。您可以在Where 子句中使用它来仅返回与所需枚举匹配的类的实例。询问我在这一点上您是否需要帮助。

     public void MethodToGetInstances()
     {
            IEnumerable<AbstractDto> dtos = typeof(AbstractDto)
                .Assembly.GetTypes()
                .Where(t => t.IsSubclassOf(typeof(AbstractDto)) && !t.IsAbstract)
                .Select(t => (AbstractDto)Activator.CreateInstance(t))
                .OrderBy(x => ((DtoEnumAttribute)x.GetType().GetCustomAttributes(typeof(DtoEnumAttribute), false).FirstOrDefault()).Enum);
    
            //If you have parameters on you Dto's, you might pass them to CreateInstance(t, params)
    
     }
    
    Run Code Online (Sandbox Code Playgroud)

dtos列表中,您将拥有所需的实例。希望能帮助到你!