使用通用转换器,将目标派生类列表中的对象与派生源类列表中的对象一起更新

时间:2019-05-31 11:12:55

标签: c# generics

我有一个从基本源类派生的源类的列表和一个从基本目标类派生的目标类的列表。与源类对应的只有一个目标类。我想制作一个通用转换器,以给定相应的源对象来更新现有的目标对象。

已完全更新:

我有以下代码:

using System;

namespace ConsoleApp1
{
    internal class Program
    {
    private static void Main(string[] args)
    {
        S1 newItem = new S1()
        {
            Age = 11,
            Name = "John"
        };

        D1 oldItem = new D1()
        {
            Age = 10
        };

        //there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
        // the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
        Convertor<S1, D1> convertor = new Convertor<S1, D1>(newItem, oldItem);

        S2 newItem2 = new S2()
        {
            City = "London",
            Name = "Lynda"
        };

        D2 oldItem2 = new D2()
        {
            City = "Paris"
        };

        Convertor<S2, D2> convertor2 = new Convertor<S2, D2>(newItem2, oldItem2);
        Console.ReadKey();
    }
}

public abstract class SourceDomain
{
    public string Name { get; set; }
    internal abstract void SetItem<Y>(Y oldItem) where Y : DestinationDomain;
}


public class S1 : SourceDomain
{
    public int Age { get; set; }

    internal override void SetItem<Y>(Y oldItem)
    {
        Console.WriteLine("here I want to update the age of oldItem (10) with the new value (11)");
        //oldItem.Age = Age;
    }
}

public class S2 : SourceDomain
{
    public string City { get; set; }

    internal override void SetItem<Y>(Y oldItem)
    {
        Console.WriteLine("here I want to update the city of oldItem Paris with the new value London");
        // oldItem.City = City;
    }
}

public class DestinationDomain { }
public class D1 : DestinationDomain
{
    public int Age { get; set; }
}
public class D2 : DestinationDomain
{
    public string City { get; set; }
}

public class Convertor<X, Y> where X : SourceDomain where Y : DestinationDomain
{
    protected X item;
    protected Y oldItem;

    public Convertor(X newObject, Y oldObject)
    {
        item = newObject;
        oldItem = oldObject;

        //here I want to call, depending of item type, the proper method, not the base one.
        item.SetItem(oldItem);
    }
}

}

SourceDomainDestinationDomain是基类,并且它们S1S2D1,{{1 }}等

此转换器接收两个类作为类型,并接收该类的两个对象,并尝试使用X类型的源项更新Y类型的目标项。

在上面的示例中,我想使用D2更改D1 oldItem变量的使用期限,并使用11值更改City oldItem2的使用期限,但是我无法访问{{1 }}。

2 个答案:

答案 0 :(得分:0)

这需要结合继承和泛型来完成,我们将使两者与泛型类型约束一起使用。

以下是我了解的要求:

您有一些要从“源”复制到“目标”的数据;一种数据具有年龄,一种数据具有城市,也许另一种数据具有贵宾犬或游泳馆。我们将定义一个表示以下内容的接口:“这是一个数据对象,可以从相同类型的另一个对象复制其自身的属性”,并将所有数据放入知道如何复制自身的小类中。 “我可以复制类似我的东西”界面不知道将要复制哪些属性。它只需要具体的类来实现一个内部了解这些细节的方法。

我们需要的其他东西是“源物”和“目的地物”。源事物仅需要提供可以复制的数据对象。目标事物只需要接收可以复制的数据对象。

您通过尝试将源和目标与数据项混淆来混淆自己。如果您要疯狂地尝试让您的班级一次做两个矛盾的事情,请尝试将其分成两个班级,每个班级做一件事情。

您永远不会对SourceDomain Name属性执行任何操作,因此我也不会。如果需要,我将其保留为练习。

public interface ICopyable<T>
{
    void CopyFrom(T other);
}

internal class Program
{
    private static void Main(string[] args)
    {
        var newItem = new SourceDomain<Person>
        {
            Item = new Person { Age = 11 },
            Name = "John"
        };

        var oldItem = new DestinationDomain<Person>
        {
            Item = new Person { Age = 10 }
        };

        //there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
        // the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
        Convertor<Person> convertor = new Convertor<Person>(newItem, oldItem);

        var newItem2 = new SourceDomain<Location>()
        {
            Item = new Location { City = "London" },
            Name = "Lynda"
        };

        var oldItem2 = new DestinationDomain<Location>()
        {
            Item = new Location {  City = "Paris" }
        };

        Convertor<Location> convertor2 = new Convertor<Location>(newItem2, oldItem2);
        Console.ReadKey();
    }
}

public class SourceDomain<T>
{
    public string Name { get; set; }
    public T Item { get; set;  }
}

public class DestinationDomain<T> where T : ICopyable<T>, new()
{
    public string Name { get; set; }

    public T Item { get; set; }
    public void CopyItemFrom(T other)
    {
        if (Item == null)
        {
            Item = new T();
        }
        Item.CopyFrom(other);
    }
}

//  A person is a thing which can turn itself into a copy of another Person. 
//  You could define a class Wombat : ICopyable<Locomotive>, if you wanted to be 
//  able to convert Locomotives to Wombats. You'd just add another CopyFrom()
//  overload, public void CopyFrom(Locomotive other). 
public class Person : ICopyable<Person>
{
    public int Age { get; set; }

    public void CopyFrom(Person other)
    {
        Age = other.Age;
    }
}
public class Location : ICopyable<Location>
{
    public String City { get; set; }

    public void CopyFrom(Location other)
    {
        City = other.City;
    }
}

public class Convertor<X> where X : ICopyable<X>, new()
{
    protected SourceDomain<X> item;
    protected DestinationDomain<X> oldItem;

    public Convertor(SourceDomain<X> newObject, DestinationDomain<X> oldObject)
    {
        item = newObject;
        oldItem = oldObject;

        //here I want to call, depending of item type, the proper method, not the base one.
        //newObject.Data = oldItem.Data;
        oldItem.CopyItemFrom(item.Item);
    }
}

家庭作业:

  1. 修改此代码,以便DestinationDomain.CopyItemFrom()接收源本身,而不是源项目。

  2. 我认为这是更好的编写方式。想一想为什么我可能会这么想。

  3. 严重的是,find out what ref does,并且如果您只是猜测它的含义,就永远不要在代码中再次使用关键字。不要只是在墙上扔代码,希望它能坚持下去。这样您将陷入很多令人沮丧的麻烦中。

答案 1 :(得分:0)

最后我已经做到了:

type Parser = {
  [K in keyof typeof SmsReplaceKeyEnum]: string;
}