需要通用c#方法的解决方案

本文关键字:方法 解决方案 | 更新日期: 2023-09-27 18:17:17

我正试图使我的方法通用,我被困在一个点,需要你的帮助。代码场景是,我有一个抽象类,比如MyBaseAbs,它包含常见属性:

public abstract class MyBaseAbs
{
    public string CommonProp1 { get; set; }
    public string CommonProp2 { get; set; }
    public string CommonProp3 { get; set; }
}

现在我有了子类:

public class Mychild1: MyBaseAbs
{
    public string Mychild1Prop1 { get; set; }
    public string Mychild1Prop2 { get; set; }
    public string Mychild1Prop3 { get; set; }
}

和另一个子类:

public class Mychild2: MyBaseAbs
{
    public string Mychild1Prop1 { get; set; }
    public string Mychild2Prop2 { get; set; }
}

现在我必须创建一个公共方法,它需要在Mychild1Mychild2的基础上执行一些操作,所以我所做的是:

public MyCustomClass SaveOperation<T>(T myObj)
        where T : MyBaseAbs
{
    SaveObject obj = new SaveObject();
}

所以在这个方法中,我需要编写公共代码,根据传递的子对象为SaveObject对象进行映射。如何确定传递的对象并使用相应的属性

需要通用c#方法的解决方案

一种选择是在基类中创建一个基本的Save函数,并使其成为虚函数。

然后在子类中重写该方法。这样,当您在SaveOperation中调用Save方法时,它应该从正确的子类调用适当的方法。

public abstract class MyBaseAbs
{
    public string CommonProp1 { get; set; }
    public string CommonProp2 { get; set; }
    public string CommonProp3 { get; set; }
    public virtual void Save() { }
}
public class Mychild1: MyBaseAbs
{
    public string Mychild1Prop1 { get; set; }
    public string Mychild1Prop2 { get; set; }
    public string Mychild1Prop3 { get; set; }
    public override void Save() { 
        //Implementation for Mychild1
    }
}
public class Mychild2: MyBaseAbs
{
    public string Mychild1Prop1 { get; set; }
    public string Mychild2Prop2 { get; set; }
    public override void Save() { 
        //Implementation for Mychild2
    }
}

如果不能修改业务对象,可以在SaveOperation方法中检查具体类的类型:

public MyCustomClass SaveOperation<T>(T myObj)
        where T : MyBaseAbs
{
    SaveObject obj = new SaveObject();
    if (myObj is Mychild1) {
        Mychild1 mychild1 = (Mychild1) myObj;
        // Business logic for object of type Mychild1
    } else if (myObje is Mychild2) {
        Mychild2 mychild2 = (Mychild2) myObj;
        // Business logic for object of type Mychild2
    }
}

请注意,这不是一个非常可靠的解决方案,因为,如果您正在创建实现抽象类的新对象,您将不得不记住在if语句中添加另一个分支。

正如@BojanB所提到的,显而易见的解决方案是在基类中创建一个虚拟方法,并在派生类中重写它,但是如果不能修改那里的代码,那么可以为每个派生类创建一个方法,并创建一个字典,将每种类型映射到它的方法:

private Dictionary<Type, Action<MyBaseAbs, MyCustomClass>> _saveOperations = 
                            new Dictionary<Type, Action<MyBaseAbs, MyCustomClass>>();
//You can then set an entry for each of your derived classes
_saveOperations[typeof(Mychild1)] = (myObj, myCustomObj) =>
{
    //Mychild1-specific logic
};
public MyCustomClass SaveOperation(MyBaseAbs obj)
{
    //do the common saving operations here 
    var result = new MyCustomClass();
    //....
    var actualType = obj.GetType();
    if(_saveOperations.ContainsKey(actualType))
    {
        _saveOperations[actualType](obj, result);
    }
    return result;
}

然后可以为每个派生类添加一个项到字典中。它与使用is操作符的概念相同,但允许您为更多派生类型添加方法,而无需修改原始SaveOperation方法

你可以这样使用c#的as - operator:

Mychild1 child1 = myObj as Mychild1;
if(child1 != null) {
   //Here you can use child1.Mychild1Prop1 forexample
}

链接到msdn: https://msdn.microsoft.com/en-us/library/cscsdfbt.aspx