C#使用OfType根据类型获取集合
首先我们来看MSDN对OfType的定义
根据描述可知,OfType在Linq的命名空间下,是IEnumerable的扩展方法,泛型的输入和输出是一样的,所以这个方法可以是协变的,但是微软并没有这么做,原因应该是协变是在.net framework 4.0之后才实现的,而OfType早于4.0,微软并没有特意再做修改了。
该方法可以将IEnumerable集合做类型区分。
我们来看基本用法
public class Animal { public string Name { get; set; } public int Age { get; set; } } public class Cat : Animal { } public class Dog : Animal { } static void Main(string[] args) { List<Animal> animals = new List<Animal> { new Cat(){ Name="Tom", Age=3}, new Cat(){ Name="Jeck", Age=3}, new Dog(){ Name="Bob", Age=3}, new Dog(){ Name="John", Age=3} }; var cats = animals.OfType<Cat>().ToList(); //output Tom,Bob var dogs = animals.OfType<Dog>().ToList(); //output Bob,John var animalsOut = animals.OfType<Animal>().ToList(); //output all }
我们可以看到,使用OfType,将集合根据泛型进行进一步的细分。当然,如果采用Object的封包拆包也可以达到同样效果,但是效率上就会差很多了。
进阶用法
我们知道,映射是计算机编程的一种重要思想,映射字典提供了不同系统间交互的可能,接下来我们将采用OfType来动态获取映射字典。
假设现在有三家公司的映射字典如下:
public static class DicBook
{
public static Dictionary<string, string> CompanyADic { get; } = new Dictionary<string, string>
{
{"xingming","name" },
{"nianling","age" },
};
public static Dictionary<string, string> CompanyBDic { get; } = new Dictionary<string, string>
{
{"xm","name" },
{"xl","age" },
};
public static Dictionary<string, string> CompanyCDic { get; } = new Dictionary<string, string>
{
{"name","name" },
{"age","age" },
};
}
建立这三个映射的相关类,作为动态解析的依据
public class ComapnyA { }
public class ComapnyB { }
public class ComapnyC { }
那么我们如何使用OfType来动态解析映射关系呢?请直接看下面的代码
public interface IPropertyMapping { } public class PropertyMapping<TSource> : IPropertyMapping { public Dictionary<string, string> MappingDictionary { get; set; } public PropertyMapping(Dictionary<string, string> mappingDictionary) { MappingDictionary = mappingDictionary; } } private static List<IPropertyMapping> propertyMappings = new List<IPropertyMapping>(); static void Main(string[] args) { propertyMappings.Add(new PropertyMapping<ComapnyA>(DicBook.CompanyADic)); propertyMappings.Add(new PropertyMapping<ComapnyB>(DicBook.CompanyADic)); propertyMappings.Add(new PropertyMapping<ComapnyC>(DicBook.CompanyADic)); var a = propertyMappings.OfType<PropertyMapping<ComapnyA>>().ToList(); //输出{"xingming","name" },{"nianling","age" }
var b = propertyMappings.OfType<PropertyMapping<ComapnyB>>().ToList(); //Output DicBook.CompanyBDic Info
var c = propertyMappings.OfType<PropertyMapping<ComapnyC>>().ToList(); //Output DicBook.CompanyCDic Info
}
上面代码,PropertyMapping 类 包含一个字典类型,继承自 IPropertyMapping ,同时定义了一个集合类型为 IPropertyMapping 的 propertyMappings 集合
通过Add方法添加具体字典,并且传入类的泛型,这样就可以通过OfType按照添加时的类型来解析出映射字典了。
看到这里,也许有人觉得搞了这么多,还不如直接使用DicBook的静态类来的方便。但是,因为CompanyA ComapnyB ComapnyC 类型可以通过反射获得,所以,这样做实现了动态获取。
接下来,我将封装到一个服务类中,采用IOC容器的注册,方便以后的复用
namespace MyApp.Services
{
public interface IPropertyMapping
{
}
public class PropertyMapping<TSource> : IPropertyMapping
{
public Dictionary<string, string> MappingDictionary { get; set; }
public PropertyMapping(Dictionary<string, string> mappingDictionary)
{
MappingDictionary = mappingDictionary;
}
}
public interface IPropertyMappingService
{
Dictionary<string, string> GetPropertyMapping<TSource>();
}
public class PropertyMappingService : IPropertyMappingService
{
private IList<IPropertyMapping> _propertyMappings { get; set; }
public PropertyMappingService(IList<IPropertyMapping> propertyMappings)
{
_propertyMappings = propertyMappings;
}
public Dictionary<string, string> GetPropertyMapping<TSource>()
{
if (_propertyMappings == null)
{
throw new ArgumentNullException(nameof(_propertyMappings));
}
//获得匹配的映射对象
var matchingMapping =
_propertyMappings.OfType<PropertyMapping<TSource>>();
if (matchingMapping.Count() == 1)
{
return matchingMapping.First().MappingDictionary;
}
else
{
throw new Exception(
$"Cannot find only one exact property mapping instance for<{typeof(TSource)}>"
);
}
}
}
}
注册到ICO
public void ConfigureServices(IServiceCollection services)
{
IServices.PropertyMappingService propertyMappingService = new IServices.PropertyMappingService(
new List<IPropertyMapping>()
{
new PropertyMapping<ComapnyA>(DicBook.CompanyADic),
new PropertyMapping<ComapnyB>(DicBook.CompanyADic),
new PropertyMapping<ComapnyC>(DicBook.CompanyADic)
}
);
services.AddSingleton<IServices.IPropertyMappingService>(propertyMappingService);
}
调用
public CalculateController(Services.IPropertyMappingService propertyMappingService) { _propertyMappingService = propertyMappingService; var aDic = _propertyMappingService.GetPropertyMapping<ComapnyA>(); //输出{"xingming","name" },{"nianling","age" }
var bDic = _propertyMappingService.GetPropertyMapping<ComapnyB>();
var cDic = _propertyMappingService.GetPropertyMapping<ComapnyC>();
}
翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 百度翻译 译
翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 百度翻译 译