2017-10-08 124 views
0

我想用一个代码行生成正确的对象,而不是开关的情况下,因为总是添加新设备时,我必须添加一个新行。对象反射c#

是否有可能在一行没有开关的情况下做到这一点?

public static Device GetDevice(Device.enumDevice TypeOfDevice, string alias) 
{ 
    // Create the Object with using reflection 

    switch (TypeOfDevice) 
    { 
     case Device.enumDevice.A34411: 
      return new A34411(string alias); 
      break; 
     case Device.enumDevice.N5744: 
      return new N5744(string alias); 
      break; 
     default: 
      throw new NotImplementedException(); 
    } 

    return null; 
} 
+0

你在哪里使用反射? – oerkelens

+1

您可以在类上使用自定义属性并使用反射,枚举'Device'基类的所有子类,然后使用正确的值查找该属性。 –

+1

那么你的计划是去除enum的使用呢? –

回答

0

优雅的方法是使用依赖注入与“命名类型注册记忆”

3

你可以在工厂方法为代表存储在一个字典

private static Dictionary<Device.enumDevice, Func<string, Device>> _factoryDict = 
    new Dictionary<Device.enumDevice, Func<string, Device>>{ 
     [Device.enumDevice.A34411] = (alias) => new A34411(alias), 
     [Device.enumDevice.N5744] = (alias) => new N5744(alias), 
    }; 

... 

public static Device GetDevice(Device.enumDevice TypeOfDevice, string alias) 
{ 
    if (_factoryDict.TryGetValue(TypeOfDevice, out var factory)) { 
     return factory(alias); 
    } 
    throw new NotImplementedException(); 
    // No retun statement here, as it would be unreachable because of the throw statement. 
} 

或者,使用反射:

const string deviceNameSpace = "MyName.MyProject.Devices."; 

public static Device GetDevice(Device.enumDevice deviceType, string alias) 
{ 
    string typeName = deviceNameSpace + deviceType.ToString(); 
    Type type = Type.GetType(typeName, throwOnError: true); 
    return (Device)Activator.CreateInstance(type, alias); 
} 
+0

第二个示例不正确。 Type.GetType在最简单的情况下需要“namespace.class”,但最好使用完整的AssemblyQualifiedName。 – arndtdv

+0

@arndtdv:你说得对。如果这些类在同一个程序集中,则可以省略AssemblyQualifiedName。 –

0

快速,但不是一个完整的例子:

public abstract class Device 
{ 
    protected Device(string alias) 
    { 
     Alias = alias; 
    } 
    public string Alias { get; } 
} 

public class A1 : Device 
{ 
    public A1(string alias) : base(alias) { } 
} 

public class A2 : Device 
{ 
    public A2(string alias) : base(alias) { } 
} 

class DeviceAttribute : Attribute 
{ 
    public DeviceAttribute(Type type) 
    { 
     Type = type; 
    } 

    public Type Type { get; } 
} 

public enum DeviceEnum 
{ 
    [Device(typeof(A1))] 
    A1, 
    [Device(typeof(A2))] 
    A2 
} 

public static class DeviceEnumExtension 
{ 
    public static Device GetInstance(this DeviceEnum obj, string alias) 
    { 
     var member = typeof(DeviceEnum).GetMember(obj.ToString()); 

     if (member[0].GetCustomAttributes(typeof(DeviceAttribute), false)[0] is DeviceAttribute deviceAttr) 
     { 
      var ctor = deviceAttr.Type.GetConstructor(new[] {typeof(string)}); 
      return ctor.Invoke(new object[] {alias}) as Device; 
     } 
     return null; 
    } 
} 

public class UnitTest1 
{ 
    [Fact] 
    public void Test1() 
    { 
     // Arrange 
     var a1 = DeviceEnum.A1; 
     var a2 = DeviceEnum.A2; 

     // Act 
     var instanceA1 = a1.GetInstance("A1"); 
     var instanceA2 = a2.GetInstance("A2"); 

     // Assert 
     Assert.Equal(typeof(A1), instanceA1.GetType()); 
     Assert.Equal(typeof(A2), instanceA2.GetType()); 
     Assert.Equal("A1", instanceA1.Alias); 
     Assert.Equal("A2", instanceA2.Alias); 
    } 
}