Unity: Conditional resolving

泪湿孤枕 提交于 2019-12-11 16:20:14

问题


I'm looking to use Unity to resolve types at runtime based on specific data received. My code (similar to that shown below) currently registers the types in a bootstrapper class at start-up and then within the main flow a decision is made on what type is required.

What I'm looking to do is replace the code lines that use the 'new' keyword with a resolver, however as this code is outwith my bootstrapper I'm not sure how this can be done...I'm new to Unity so please go easy.

// In Bootstrapper class
resolver.RegisterType<IDataType1, DataType1>();
resolver.RegisterType<IDataType2, DataType2>();
resolver.RegisterType<IDataType3, DataType3>();


// Main flow...outwith bootstrapper
switch (dataRecordType)
{
    case DataRecordType.dataType1:
        DataType1 dt1 = new DataType1();
        dt1.ProcessData();
        break;

    case DataRecordType.dataType2:
        DataType2 dt2 = new DataType2();
        dt2.ProcessData();
        break;

    case DataRecordType.dataType3:
        DataType3 dt3 = new DataType3();
        dt3.ProcessData();
        break;

    default:
        break;
}

回答1:


You are missing a few abstractions here. You're missing an general abstraction over your data types and an abstraction for creating implementations of those data types:

// In your core layer
public interface IDataType {
    void ProcessData();
}

public interface IDataTypeFactory {
    IDataType Create(DataRecordType dataRecordType);
}

// In Bootstrapper class
resolver.RegisterInstance<IDataTypeFactory>(new DataTypeFactory(resolver));
resolver.RegisterType<IDataType1, DataType1>();
resolver.RegisterType<IDataType2, DataType2>();
resolver.RegisterType<IDataType3, DataType3>();

private sealed class DataTypeFactory : IDataTypeFactory {
    private readonly IUnityContainer container;
    public DataTypeFactory(IUnityContainer container) {
        this.container = container;
    }

    public IDataType Create(DataRecordType dataRecordType) {
        switch (dataRecordType) {
            case DataRecordType.dataType1:
                return this.container.Resolve<IDataType1>();
            case DataRecordType.dataType2:
                return this.container.Resolve<IDataType2>();
            case DataRecordType.dataType3:
                return this.container.Resolve<IDataType3>();
            default:
                throw new InvalidEnumArgumentException();
        }
    }
}

What you can see is that the code for creating implementations is moved to the factory. Now the remaining application code can be comes something like this:

// Main flow...outwith bootstrapper
IDataType dt = this.dataTypeFactory.Create(dataRecordType);
dt.ProcessData();

The IDataType1, IDataType2 and IDataType3 are now only used in the bootstrapper and have become redundant (or at least, redundant with the code you presented), so you could even remove them all together and change the bootstrap logic to the following:

// In Bootstrapper class
resolver.RegisterInstance<IDataTypeFactory>(new DataTypeFactory(resolver));
resolver.RegisterType<DataType1>();
resolver.RegisterType<DataType2>();
resolver.RegisterType<DataType3>();

private sealed class DataTypeFactory : IDataTypeFactory {
    private readonly IUnityContainer container;
    public DataTypeFactory(IUnityContainer container) {
        this.container = container;
    }

    public IDataType Create(DataRecordType dataRecordType) {
        switch (dataRecordType) {
            case DataRecordType.dataType1:
                return this.container.Resolve<DataType1>();
            case DataRecordType.dataType2:
                return this.container.Resolve<DataType2>();
            case DataRecordType.dataType3:
                return this.container.Resolve<DataType3>();
            default:
                throw new InvalidEnumArgumentException();
        }
    }
}


来源:https://stackoverflow.com/questions/26607434/unity-conditional-resolving

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!