我创建了question,并意识到这是由于我的某些设计错误所致。但是,我确实认为该概念可能有用,并且我想知道如果可能的话,如何解决类似的问题。
我想创建一个将两个数字相加的算法,无论是string
还是int
。我还希望能够在控制台中输出所有内容,并希望避免代码重复。我创建了一个generic interface
,它会根据模型而变化。然后是一个处理两个成员加法的类。请注意,数据来自处理程序类(在现实生活中,它们从外部数据获取信息以填充模型)。
请注意,我确实知道有很多更简单的掺杂方法,但是我想了解为什么它不起作用。现在,该代码无法在{{ 1}}归因于ValidateHandler<T>(IAddHandler<T> handler)
。为什么不能选择正确的覆盖方法?我尝试将泛型添加到重写的方法中,但仍然无法正常工作。如何使cannot convert from 'T' to 'Test.Models.StringModel'
从类型中选择正确的方法?
这是我写的代码。
型号:
ValidateHandler<T>
接口:
public class IntegerModel
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}
public class StringModel
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
处理程序:
public interface IAddHandler<T>
{
T Add();
void GetData();
}
这里是主要功能
public class IntegerHandler : IAddHandler<IntegerModel>
{
public IntegerModel IntegerModel { get; set; }
public void GetData()
{
// Get Info to Add from external file for example
IntegerModel = new IntegerModel { A = 10, B = 20 };
}
public IntegerModel Add()
{
IntegerModel.C = IntegerModel.A + IntegerModel.B;
return IntegerModel;
}
}
public class StringHandler : IAddHandler<StringModel>
{
public StringModel StringModel { get; set; }
public void GetData()
{
// Get Info to Add from external file for example
StringModel = new StringModel { A = "10", B = "20" };
}
public StringModel Add()
{
StringModel.C = StringModel.A + StringModel.B;
return StringModel;
}
}
我知道我可以执行以下操作,但是这样做似乎无效,因此我看不到使用泛型的意义。
public static void Main(string[] args)
{
var integerHandler = new IntegerHandler();
var stringHandler = new StringHandler();
ValidateHandler(integerHandler);
ValidateHandler(stringHandler);
}
public static void ValidateHandler<T>(IAddHandler<T> handler)
{
handler.GetData();
var result = handler.Add();
WriteResults(result);
}
public static void WriteResults(StringModel model)
{
Console.WriteLine(model.C);
}
public static void WriteResults(IntegerModel model)
{
Console.WriteLine(model.C);
}
答案 0 :(得分:2)
这就是我的建议。这种方法对泛型的投入较小。我相信,比起完全通用的解决方案,要更容易动手。
public interface IResult
{
Object Result { get; }
}
public interface IModel : IResult
{
Object A { get; }
Object B { get; }
}
public class Model<T> : IModel
{
public T A { get; set; }
public T B { get; set; }
public T Result { get; set; }
// The "IModel.*" prefix means this is an "explicit" implementation of the IModel
// interface. That means that ordinarily, model.A gets you the above strongly typed
// A property, but with an explicit cast to IModel, you get the non-generic IModel
// version: model.A is int or whatever T is; ((IModel)model).A is object.
//
// These getters don't recurse because this is of type Model<T>, not IModel.
// If T is List<String>, a subclass could override this to return
// String.Join(", ", Result);
Object IModel.A => A;
Object IModel.B => B;
Object IResult.Result => Result;
}
public interface IAddHandler<T> where T : IModel
{
T Model { get; set; }
T Add();
void GetData();
}
public class IntegerHandler : IAddHandler<Model<int>>
{
public Model<int> Model { get; set; }
public void GetData()
{
// Get Info to Add from external file for example
Model = new Model<int> { A = 10, B = 20 };
}
public Model<int> Add()
{
Model.Result = Model.A + Model.B;
return Model;
}
}
public class StringHandler : IAddHandler<Model<string>>
{
public Model<string> Model { get; set; }
public void GetData()
{
// Get Info to Add from external file for example
Model = new Model<string> { A = "10", B = "20" };
}
public Model<string> Add()
{
Model.Result = Model.A + Model.B;
return Model;
}
}
主要:
class Program
{
public static void Main(string[] args)
{
var integerHandler = new IntegerHandler();
var stringHandler = new StringHandler();
ValidateHandler(integerHandler);
ValidateHandler(stringHandler);
}
// This method must require T to be IModel because IAddHandler<T> requires
// T to be IModel.
public static void ValidateHandler<T>(IAddHandler<T> handler) where T : IModel
{
handler.GetData();
var result = handler.Add();
// IModel inherits from IResult. Hence, anything that implements IModel
// must implement IResult. So this is an implicit cast, even though IResult
// is implemented explicitly.
WriteResults(result);
}
// The parameter here could be IModel instead, but maybe there are other non-model
// classes that implement IResult.
public static void WriteResults(IResult result)
{
Console.WriteLine(result.Result);
}
}