c#向接口动态添加属性
我有一个asp.net核心Web服务,它需要正确处理对象的接口属性(必须找出用于json字符串反序列化的实现) 因此,我创建了一个从接口属性调用的类,如:c#向接口动态添加属性,c#,asp.net-core,.net-core,.net-standard,C#,Asp.net Core,.net Core,.net Standard,我有一个asp.net核心Web服务,它需要正确处理对象的接口属性(必须找出用于json字符串反序列化的实现) 因此,我创建了一个从接口属性调用的类,如: [JsonConverter(typeof(InterfaceJsonConverter<IInputFormat>))] public interface IInputFormat { // ... } [JsonConverter(类型(InterfaceJsonConverter))] 公共接口IIInputFor
[JsonConverter(typeof(InterfaceJsonConverter<IInputFormat>))]
public interface IInputFormat
{
// ...
}
[JsonConverter(类型(InterfaceJsonConverter))]
公共接口IIInputFormat
{
// ...
}
定义InterfaceJsonConverter的模型类必须是不支持程序集加载的.NET标准1.4。
但这种技术用于找出哪个程序集具有接口的实现,以及哪个实现最接近json对象。
(我当然可以直接将接口添加到类中,而不是读取程序集,但我想要一个动态解决方案,我永远不会错过一个实现)
(最初我是在.NET4.6中开发的,在那里工作得很好)
所以我现在要做的是:
public class InterfaceJsonConverter<T> : Newtonsoft.Json.JsonConverter
{
public InterfaceJsonConverter()
{
this.DerivedTypes = GetTypesOfImplementedInterfaces(typeof(T));
}
readonly HashSet<Type> derivedTypes = new HashSet<Type>();
public InterfaceJsonConverter(params Type[] types)
{
this.DerivedTypes = types;
}
public InterfaceJsonConverter(System.Reflection.Assembly assembly, string @namespace)
{
this.DerivedTypes = GetTypesInNamespace(assembly, @namespace);
}
private Type[] GetTypesOfImplementedInterfaces(Type type)
{
var parts = type.AssemblyQualifiedName.Split(',');
var assemblyName = parts[1].Trim();
var assemblies = AssemblyRepo.GetReferencingAssemblies(assemblyName);
//var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var types = new List<Type>();
foreach (var a in assemblies)
{
try
{
//type.GetInterfaces().Any(i => i.FullName == typeof(T).FullName)
var currentTypes = a.GetTypes().Where(t => t.GetTypeInfo().IsAbstract==false && t.GetInterfaces().Any(i => i.FullName == type.FullName)).ToList();
types.AddRange(currentTypes);
}
catch (System.Exception) { }// ignored}
}
if(types.Count==0)
throw new System.Exception("No class found which implements interface [" + typeof(T) + "].");
return types.ToArray();
}
private Type[] GetTypesInNamespace(System.Reflection.Assembly assembly, string @namespace)
{
//return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray();
return assembly.GetTypes()
.Where(
type => String.Equals(type.Namespace, @namespace)
&& type.GetInterfaces().Any(i => i.FullName == typeof (T).FullName)
).ToArray();
}
public IEnumerable<Type> DerivedTypes
{
get
{
return derivedTypes.ToArray();
}
set
{
if (value == null)
throw new ArgumentNullException();
derivedTypes.Clear();
derivedTypes.UnionWith(value);
}
}
JsonObjectContract FindContract(JObject obj, JsonSerializer serializer)
{
List<JsonObjectContract> bestContracts = new List<JsonObjectContract>();
foreach (var type in derivedTypes)
{
if (type.GetTypeInfo().IsAbstract)
continue;
var contract = serializer.ContractResolver.ResolveContract(type) as JsonObjectContract;
if (contract == null)
continue;
if (obj.Properties().Select(p => p.Name).Where(n => n != "$type").Any(n => contract.Properties.GetClosestMatchProperty(n) == null))
continue;
if (bestContracts.Count == 0 || bestContracts[0].Properties.Count > contract.Properties.Count)
{
bestContracts.Clear();
bestContracts.Add(contract);
}
else if (contract.Properties.Count == bestContracts[0].Properties.Count)
{
bestContracts.Add(contract);
}
}
return bestContracts.Count > 0 ? bestContracts.Single() : null;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var obj = JObject.Load(reader); // Throws an exception if the current token is not an object.
if (obj["$type"] != null && serializer.TypeNameHandling != TypeNameHandling.None)
{
// Prevent infinite recursion when using an explicit converter in the list.
var removed = serializer.Converters.Remove(this);
try
{
// Kludge to prevent infinite recursion when using JsonConverterAttribute on the type: deserialize to object.
return obj.ToObject(typeof (object), serializer);
}
finally
{
if (removed)
serializer.Converters.Add(this);
}
}
var contract = FindContract(obj, serializer);
if (contract == null)
throw new JsonSerializationException("no contract found for " + obj.ToString());
if (existingValue == null || !contract.UnderlyingType.IsInstanceOfType(existingValue))
//!contract.UnderlyingType.IsAssignableFrom(existingValue.GetType()))
existingValue = contract.DefaultCreator();
//will call the default constructor(PARAMETERLESS)...MAKE SURE YOUR CLASS HAS ONE!!!!!
using (var sr = obj.CreateReader())
{
serializer.Populate(sr, existingValue);
}
return existingValue;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
公共类接口JsonConverter:Newtonsoft.Json.JsonConverter
{
公共接口转换器()
{
this.DerivedTypes=getTypeSofImplementedInterface(typeof(T));
}
readonly HashSet-derivedTypes=新HashSet();
公共接口JSONConverter(参数类型[]类型)
{
this.DerivedTypes=类型;
}
公共接口JSONConverter(System.Reflection.Assembly程序集,字符串@命名空间)
{
this.DerivedTypes=GetTypesInNamespace(程序集,@namespace);
}
私有类型[]GetTypesOfImplementedInterface(类型)
{
var parts=type.AssemblyQualifiedName.Split(',');
var assemblyName=零件[1]。修剪();
var assemblies=AssemblyRepo.GetReferenceGassemblies(assemblyName);
//var assemblies=AppDomain.CurrentDomain.GetAssemblies();
变量类型=新列表();
foreach(程序集中的变量a)
{
尝试
{
//type.GetInterfaces().Any(i=>i.FullName==typeof(T.FullName)
var currentTypes=a.GetTypes()。其中(t=>t.GetTypeInfo().IsAbstract==false&&t.GetInterfaces().Any(i=>i.FullName==type.FullName)).ToList();
类型。添加范围(当前类型);
}
catch(System.Exception){}//ignored}
}
if(types.Count==0)
抛出新的System.Exception(“未找到实现接口[“+typeof(T)+”])的类”;
返回类型。ToArray();
}
私有类型[]GetTypesInNamespace(System.Reflection.Assembly程序集,string@namespace)
{
//返回assembly.GetTypes().Where(t=>String.Equals(t.Namespace,Namespace,StringComparison.Ordinal)).ToArray();
返回assembly.GetTypes()
.在哪里(
type=>String.Equals(type.Namespace,@Namespace)
&&type.GetInterfaces().Any(i=>i.FullName==typeof(T.FullName)
).ToArray();
}
公共IEnumerable派生类型
{
得到
{
返回derivedTypes.ToArray();
}
设置
{
如果(值==null)
抛出新ArgumentNullException();
derivedTypes.Clear();
derivedTypes.UnionWith(值);
}
}
JsonObjectContract FindContract(JObject对象,JsonSerializer序列化程序)
{
List bestContracts=新列表();
foreach(派生类型中的变量类型)
{
if(type.GetTypeInfo().IsAbstract)
继续;
var contract=serializer.ContractResolver.ResolveContract(类型)作为JsonObjectContract;
如果(合同==null)
继续;
if(obj.Properties().Select(p=>p.Name).Where(n=>n!=“$type”).Any(n=>contract.Properties.GetClosestMatchProperty(n==null))
继续;
if(bestContracts.Count==0 | | bestContracts[0].Properties.Count>contract.Properties.Count)
{
bestContracts.Clear();
最佳合同。添加(合同);
}
else if(contract.Properties.Count==bestContracts[0].Properties.Count)
{
最佳合同。添加(合同);
}
}
返回bestContracts.Count>0?bestContracts.Single():null;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(T);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.Null)
返回null;
var obj=JObject.Load(reader);//如果当前标记不是对象,则引发异常。
if(obj[“$type”!=null&&serializer.typenameholling!=typenameholling.None)
{
//在列表中使用显式转换器时防止无限递归。
var removed=serializer.Converters.Remove(此);
尝试
{
//在类型上使用JSONConverterateAttribute时防止无限递归的困难:反序列化到对象。
返回obj.ToObject(typeof(object),序列化器);
}
最后
{
如果(已删除)
serializer.Converters.Add(此);
}
}
var合同=FindContract(obj,序列化程序);
如果(合同==null)
抛出新的JsonSerializationException(“未找到“+obj.ToString()的合同”);
if(existingValue==null | |!contract.underyingType.IsInstanceOfType(exis