减少构造器锅炉板代码
本文关键字:代码 构造器 | 更新日期: 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;
}
}
这与你的第二个解决方案非常相似,但它不会失去类型安全性。
我目前处于
Dog
和Cat
类存在于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();
}
}