Một lựa chọn thay thế sử dụng Reflection và làm theo tấm Strategy Pattern.
1) Tạo một lớp cơ sở cho lập luận của các nhà xây dựng
public abstract class ConstructorArgs
{
}
2) Tạo một chuỗi các lớp đối số bê tông khác nhau:
public class StringArg : ConstructorArgs
{
public string _gradeTypeStringFromXmlFile { get; set; }
public StringArg (string gradeTypeStringFromXmlFile)
{
this._gradeTypeStringFromXmlFile = gradeTypeStringFromXmlFile ;
}
}
public class EnumArg : ConstructorArgs
{
public Enum.GradeType _gradeType { get; set; }
public EnumArg (Enum.GradeType gradeType)
{
this._gradeType = gradeType ;
}
}
3) Bây giờ trong lớp GradeType bạn tạo ra các phương pháp cần thiết cho Reflection. ParseArguments quét các arg cho các thuộc tính và đối với mỗi thuộc tính mà nó tìm thấy, nó sao chép giá trị của nó vào thuộc tính tương ứng của GradeType bằng cách sử dụng SetProperty.Kể từ khi nó sử dụng tên tài sản cho phù hợp, điều quan trọng là để giữ cho tên thuộc tính như nhau trên cả GradeType và ConstructorArgs bê tông:
private void SetProperty(String propertyName, object value)
{
var property = this.GetType().GetProperty(propertyName);
if (property != null)
property.SetValue(this, value);
}
private void ParseArguments(ConstructorArgs args)
{
var properties = args.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
this.SetProperty(propertyInfo.Name,
args.GetType().GetProperty(propertyInfo.Name).GetValue(args));
}
}
4) Trong lớp GradeType bạn tạo các thuộc tính tương ứng (nhớ rằng bạn phải sử dụng chính xác cùng tên và các loại mà bạn sử dụng trong ConstructorArgs bê tông nhưng bạn có thể sử dụng bất kỳ bổ truy cập mà bạn thích)
public string _gradeTypeStringFromXmlFile { get; set; }
public Enum.GradeType _gradeType { get; set; }
5) Tạo một constructor cho lớp GradeType của bạn với một tham số kiểu ConstructorArgs:
public GradeType(ConstructorArgs args)
{
this.ParseArguments(args);
}
6) Bây giờ bạn có thể đăng ký GradeType trong Unity sử dụng một constructor đơn nhưng bạn có thể vượt qua trong các loại khác nhau như các đối số khi giải quyết nó:
_unityContainer.RegisterType<IGradeType, GradeType>(
new InjectionConstructor(typeof(ConstructorArgs)));
var args1 = new StringArg(gradeTypeStringFromXmlFile); // string
IGradeType gradeType1 = _unityContainer.Resolve<IGradeType>(
new ResolverOverride[]{new ParameterOverride("args", args1)});
var args2 = new EnumArg(gradeType); // enum
IGradeType gradeType2 = _unityContainer.Resolve<IGradeType>(
new ResolverOverride[]{new ParameterOverride("args", args2)});
Nếu bạn đang có kế hoạch liên tục giải quyết kiểu của bạn trong một lần lặp cách tiếp cận đó có thể không lý tưởng, vì Reflection đi kèm với một hình phạt hiệu suất.
tại sao không sử dụng 'Enum.Parse' trên chuỗi classType trước khi tạo lớp? – jgauffin
nó chỉ cảm thấy giống như một thiết kế trực quan mà lớp GradeType chuyển đổi chuỗi. – FatAlbert
Nó có vẻ là một giải pháp dễ vỡ đối với tôi vì bất kỳ giá trị không tồn tại nào sẽ ném một ngoại lệ hoặc ẩn một lỗi. – jgauffin