c#向接口动态添加属性

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

我有一个asp.net核心Web服务,它需要正确处理对象的接口属性(必须找出用于json字符串反序列化的实现)

因此,我创建了一个从接口属性调用的类,如:

[JsonConverter(typeof(InterfaceJsonConverter<IInputFormat>))]
public interface IInputFormat
{
    // ...
}
[JsonConverter(类型(InterfaceJsonConverter))]
公共接口IIInputFormat
{
// ...
}
定义InterfaceJsonConverter的模型类必须是不支持程序集加载的.NET标准1.4。 但这种技术用于找出哪个程序集具有接口的实现,以及哪个实现最接近json对象。 (我当然可以直接将接口添加到类中,而不是读取程序集,但我想要一个动态解决方案,我永远不会错过一个实现)

(最初我是在.NET4.6中开发的,在那里工作得很好)

所以我现在要做的是:

  • 创建新的.NET标准1.6库
  • 将InterfaceJsonConverter放入该库中
  • 从接口中删除属性
  • 在运行时添加接口属性
  • 有没有办法把这个存档? 还是有更好的方法来处理asp.net核心中的接口

    为了完整起见,我将发布InterfaceJsonConverter的代码

    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