通用化方法和要传递的参数

时间:2016-12-18 08:32:40

标签: c# generics

我正在尝试学习泛型并在以下代码中实现它。我是这个概念的新手,所以它可能不是最好的方法,所以我对任何事情持开放态度。

我有一个方法,它接受一个类并将其映射到一个新类的对象并返回:

 public OtherClass CreateNeed(long id, string name, int needTypeId)
    {
        var newDto = new OtherClass();
        newDto.Id = id;
        newDto.Name = name;
        newDto.NeedTypeId = needTypeId;

        return newDtoToAdd;
    }

这就是我所说的:

var needClass = new NeedClass();
var addedNeed = CreateNeed(needClass.id, needClass.name, needClass.needTypeId);

但有时,我需要映射的对象是相同的OtherClass ...所以我这样称呼..

var otherClass = new OtherClass();
var otherAddedNeed = CreateNeed(otherClass.id, otherClass.name, otherClass.needTypeId);

我想将它作为泛型类型传递,因此CreateNeed方法可以处理这两种类型......可能是这样的:

var needClass = new NeedClass();
var addedNeed = CreateNeed<NeedClass>(needClass);

var otherClass = new OtherClass();
var addedNeed = CreateNeed<OtherClass>(otherClass);

我发现自己经常在我的代码中遇到这种问题,并且只需要传入部分类来修改,但返回总是返回相同类型的对象。我也试图一般地学习泛型,那么如何修改方法以及随后的调用进行泛化?

3 个答案:

答案 0 :(得分:1)

选项很少。首先,您根本不需要通用方法来实现这一目标。当然,你可以用泛型来做到这一点,但不一定。

第一个选项,您创建一个接口以匹配两个类结构,并让非泛型方法接受此接口作为参数。

//Implement this interface with your 2 classes
public interface IClass
{
   int Id {get;set;}
   //other fields here.
}

public interface OtherClass : IClass
{
   public int Id {get;set;}
   //other fields here.
}

public interface NeedClass : IClass
{
   public int Id {get;set;}
   //other fields here.
}

public OtherClass CreateNeed(IClass input)
 {
     var newDto = new OtherClass();
     newDto.Id = input.id;
     newDto.Name = input.name;
     newDto.NeedTypeId = input.needTypeId;    
     return newDtoToAdd;
  } 

  //example call 
  var newNeedClass = new NeedClass();
  //set all your properties here.
  newNeedClass.Id =1;
  var otherClassInstance = CreateNeed(newNeedClass );

第二个,将参数类型设为dynamic。我建议不要这样做。

thrid one ,如果您热衷于使用泛型,那么

public OtherClass CreateNeed<T>(T inp) where T: IClass 
     {
         var newDto = new OtherClass();
         newDto.Id = inp.id;
         newDto.Name = inp.name;
         newDto.NeedTypeId = inp.needTypeId;        
         return newDtoToAdd;
      }

然后您可以使用以下语法

来调用它
var newNeedClass = new NeedClass();
//set all your properties here.
newNeedClass.Id =1;
var otherClassInstance = CreateNeed(newNeedClass );

最后,您还可以使用 Automapper 等映射库来简化映射。但是,是的,这会产生对第三方框架的依赖。

答案 1 :(得分:1)

解决方案是定义具有所需属性的接口:

public interface IConvertable
{
    int id { get; set; }
    string name { get; set; }
    //...
}

在要转换为彼此的所有类中实现接口。通用方法是:

public static T CreateNeed<T>(IConvertable ToConvert) where T : IConvertable, new()
{
    T Need = new T();
    Need.id = ToConvert.id;
    Need.name = ToConvert.name;
    //...
    return Need;
}

现在可以将实现IConvertable接口的所有类转换为实现IConvertable接口的其他类(请注意,构造函数不允许使用此实现的任何参数)。用法示例:

OtherClass OldObject = new OtherClass() { id = 1, name = "test" };
NeededClass NewObject = CreateNeed<NeededClass>(OldObject);

答案 2 :(得分:1)

你也可以像这样创建mapper类:

public class Mapper
{
    public static TOutput Map<TInput, TOutput>(TInput input, Action<TInput, TOutput> mapFunc) 
        where TOutput : class, new()
    {
        TOutput t = new TOutput();
        mapFunc(input, t);
        return t;
    }
}

然后用它来表示类之间的映射:

    NeedClass c = new NeedClass { Id = 1, Name = "Name" };
    OtherClass oc = Mapper.Map<NeedClass, OtherClass>(c, (input, output) =>
    {
        output.Id = input.Id;
        output.Name = input.Name;
    });

然后定义默认的映射器函数以定期使用它,对于要部分映射的情况,请按照Action<TInput, TOutput>进行映射。

要明确现实生活场景,您不想创建这类映射器,而是使用AutoMapper代替。祝你好运。