如何创建一个有条件定义类型的对象?

时间:2017-02-15 21:39:33

标签: c# class entity

我有一系列的类,每个类都有不同的属性,每个类都有一个ID(每个类型不是每个实例)。

鉴于以下内容:

public class TestEntity : EntityBase {
    public override ushort ID { get; } = 1;
    public override void something() { do_something(); }
}
public class OtherEntity : EntityBase {
    public override ushort ID { get; } = 2;
    public override void something() { something_else(); }
}

在阅读数据时,我只有ushort

ushort EntityId = BitConverter.ToUInt16(data.GetRange(CURRENT_POSITION + TILE_ENTITY_ID_OFFSET, TILE_ENTITY_ID_LENGTH).ToArray().Reverse().ToArray(), 0);

如何使用EntityId的值根据其值创建不同类型的对象?使用ifswitch语句不是一种选择,因为将有超过200种类型。

3 个答案:

答案 0 :(得分:8)

如果我理解你的问题,可以采取一种方法(有许多方法)。

private static Dictionary<ushort, Type> TypeMap = new Dictionary<ushort, Type>()
                                                   {
                                                       { 1, typeof(TestEntity) },
                                                       { 2, typeof(OtherEntity) }
                                                   };

private EntityBase CreateEntity(ushort id)
{
    var type = TypeMap[id];
    return (EntityBase) Activator.CreateInstance(type);
}

答案 1 :(得分:3)

最好的方法是定义一个包含ID属性的Attribute-Subclass,然后使用为每种类型提供唯一ID的属性注释所有类型。
Layter您可以收集并过滤包含给定属性的加载类型,并按属性的ID属性进行过滤 使用这种方法,您可以在以后添加其他子类型,而无需修改使用代码 实现可能如下所示:

public sealed class MyCustomAttribute : Attribute
{
    public ushort Id { get; set; }

    public MyCustomAttribute(ushort id)
    {
        this.Id = id;
    }
}

public class MyDemoConsumer
{
    public void MyConsumingMethod(ushort requiredTypeId)
    {
        var requestedType = AppDomain
            .CurrentDomain
            .GetAssemblies()
            .SelectMany(asm => asm.GetTypes())
            .Where(type => type.GetCustomAttributes(typeof(MyCustomAttribute), false).Any())
            .Select(type => new { Type = type, CustomId = type.GetCustomAttributes(typeof(MyCustomAttribute), false).Cast<MyCustomAttribute>().Single().Id })
            .Where(item => item.CustomId == requiredTypeId)
            .Select(item => item.Type)
            .SingleOrDefault();

        if (requestedType != null)
        {
            var result = Activator.CreateInstance(requestedType);
        }
    }
}

答案 2 :(得分:3)

......有很多方法可以做到这一点,但这里很简单...

class Program
{
    static void Main()
    {
        var simpleFactory = new SimpleFactory();
        var entity = simpleFactory.Create(1);
        entity.Something();
    }
}

public abstract class EntityBase
{
    public abstract ushort ID { get; }
    public abstract void Something();
}

public class TestEntity : EntityBase
{
    public override ushort ID { get { return 1; } }
    public override void something() { }
}
public class OtherEntity : EntityBase
{
    public override ushort ID { get { return 2; } }
    public override void something() { }
}

public class SimpleFactory
{
    private Dictionary<ushort, Func<EntityBase>> config = new Dictionary<ushort, Func<EntityBase>>
    {
        { 1, ()=>new TestEntity()},
        { 2, ()=>new OtherEntity()},
    };

    public EntityBase Create(ushort entityId)
    {
        if (!config.ContainsKey(entityId))
            throw new InvalidOperationException();

        return config[entityId]();
    }
}