减少构造器锅炉板代码

本文关键字:代码 构造器 | 更新日期: 2023-09-27 18:08:59

我经常写这样的类:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }
    public Animal(Dog data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }
    public Animal(Cat data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }
}

当你有很多属性和类型时,你很快就会得到大量的样板代码。理想情况下,在这种情况下,我会创建一个IAnimal界面并引用它。我目前的情况是,Dog和Cat类存在于第三方程序集中,我无法修改它们。我能想到的唯一解决办法是:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }
    public Animal(Cat data){Init(data);}
    public Animal(Dog data){Init(data);}
    private void Init(dynamic data)
    {
        this.Colour = data.Colour;
        this.Weight = data.Weight;
    }
}

这工作,但我失去了所有类型安全,有一个更好的解决方案比构造函数注入?

谢谢,乔

编辑:这是一个真实世界的例子。我有一个第三方库,它返回3个对象,称为:

  • GetPageByIdResult
  • GetPagesByParentIdResult
  • GetPagesByDateResult

(这些都是从服务引用中自动生成的类,属性几乎相同)

我想处理单个PageData对象或它们的集合,而不是处理这三个对象。

减少构造器锅炉板代码

您可以将逻辑放在所有其他构造函数调用的公共构造函数中:

public class Animal
{
    public string Colour { get; set; }
    public int Weight { get; set; }
    public Animal(Dog data) : this (data.Colour, data.Weight)
    {
    }
    public Animal(Cat data) : this (data.Colour, data.Weight)
    {
    }
    private Animal(string colour, int weight)
    {
        this.Colour = colour;
        this.Weight = weight;
    }
}

这与你的第二个解决方案非常相似,但它不会失去类型安全性。

我目前处于DogCat类存在于a中的情况第三方程序集,我不能修改它们

我建议基于automapper的解决方案:

public static class AnimalFactory
{
    public static Animal Create<T>(T source)
        where T : class
    {
        Mapper.CreateMap<T, Animal>();
        return Mapper.Map<Animal>(source);
    }
}

用法:

        var catAnimal = AnimalFactory.Create(cat);
        var dogAnimal = AnimalFactory.Create(dog);

当然,如果需要,您可以提供一种自定义映射配置的方法。

如果您不想让类像这样乱七八糟,您可以尝试扩展方法?

public static Animal ToAnimal(this Dog item)
{
    return new Animal() {Weight = item.Weight, Colour = item.Colour};
}
public static Animal ToAnimal(this Cat item)
{
    return new Animal() {Weight = item.Weight, Colour = item.Colour};
}

尝试使用json序列化器,这样我们可以确保类型安全。

 public class Animal
    {
        public string Colour { get; set; }
        public long Weight { get; set; }
        public string Name { get; set; }
        public Animal Create<T>(T anyType)
        {
            return GetObject<T, Animal>(anyType);
        }
        public K GetObject<T, K>(T type1)
        {
            try
            {
                var serialized = JsonConvert.SerializeObject(type1);
                return JsonConvert.DeserializeObject<K>(serialized);
            }
            catch (Exception ex)
            {
                return default(K);
            }
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            Animal obj = new Animal();
            var animal = obj.Create(new  { Colour = "Red", Weight = 100 });
            //here you can pass any object, only same name properties will be initialized..
            Console.WriteLine(animal.Colour + " :  " + animal.Weight);
            Console.ReadKey();
        }
    }