简体   繁体   中英

Object reflection c#

I want to generate the right object with one code line and not a switch case because always when a new device is added I have to add a new line.

Is it possible to do that in one line without switch case?

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;
}

You could store the factory methods as delegates in a dictionary

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.
}

Or, using reflection:

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);
}

一种不错的方法是将依赖注入与“命名类型注册”一起使用

Fast, but not quite a complete example:

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM