Skip to content

Instantly share code, notes, and snippets.

@juanfranblanco
Created February 22, 2021 12:57
Show Gist options
  • Save juanfranblanco/b7485fc2e8c9661aea576f13e8fea2d4 to your computer and use it in GitHub Desktop.
Save juanfranblanco/b7485fc2e8c9661aea576f13e8fea2d4 to your computer and use it in GitHub Desktop.
public class PropertyOverridingTypeDescriptor : CustomTypeDescriptor
{
private readonly Dictionary<string, PropertyDescriptor> overridePds = new Dictionary<string, PropertyDescriptor>();
public PropertyOverridingTypeDescriptor(ICustomTypeDescriptor parent)
: base(parent)
{ }
public void OverrideProperty(PropertyDescriptor pd)
{
overridePds[pd.Name] = pd;
}
public override object GetPropertyOwner(PropertyDescriptor pd)
{
object o = base.GetPropertyOwner(pd);
if (o == null)
{
return this;
}
return o;
}
public PropertyDescriptorCollection GetPropertiesImpl(PropertyDescriptorCollection pdc)
{
List<PropertyDescriptor> pdl = new List<PropertyDescriptor>(pdc.Count + 1);
foreach (PropertyDescriptor pd in pdc)
{
if (overridePds.ContainsKey(pd.Name))
{
pdl.Add(overridePds[pd.Name]);
}
else
{
pdl.Add(pd);
}
}
PropertyDescriptorCollection ret = new PropertyDescriptorCollection(pdl.ToArray());
return ret;
}
public override PropertyDescriptorCollection GetProperties()
{
return GetPropertiesImpl(base.GetProperties());
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return GetPropertiesImpl(base.GetProperties(attributes));
}
}
public class TypeDescriptorOverridingProvider : TypeDescriptionProvider
{
private readonly ICustomTypeDescriptor ctd;
public TypeDescriptorOverridingProvider(ICustomTypeDescriptor ctd)
{
this.ctd = ctd;
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return ctd;
}
}
private static void AddExtendedData()
{
AddExtendedData<Service>();
AddExtendedData<Context>();
var properties = DeepCloner.GetFastDeepClonerProperties(typeof(Context));
foreach (var property in properties)
{
if (property.Name.StartsWith("AdditionalData"))
{
property.Attributes.Add(new JsonExtensionDataAttribute());
// // now test and se if exist
// prop = DeepCloner.GetFastDeepClonerProperties(typeof(test)).First();
// bool containAttr = prop.ContainAttribute<JsonIgnoreAttribute>()
//// or
// JsonIgnoreAttribute myAttr = prop.GetCustomAttribute<JsonIgnoreAttribute>();
}
}
}
private static void AddExtendedData<T>()
{
var type = typeof(T);
PropertyOverridingTypeDescriptor ctd = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(type).GetTypeDescriptor(type));
// iterate through properies in the supplied object/type
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(type))
{
// for every property that complies to our criteria
if (pd.Name.EndsWith("AdditionalData"))
{
// we first construct the custom PropertyDescriptor with the TypeDescriptor's
// built-in capabilities
PropertyDescriptor pd2 =
TypeDescriptor.CreateProperty(
type, // or just _settings, if it's already a type
pd, // base property descriptor to which we want to add attributes
// The PropertyDescriptor which we'll get will just wrap that
// base one returning attributes we need.
new JsonExtensionDataAttribute()
// this method really can take as many attributes as you like,
// not just one
);
// and then we tell our new PropertyOverridingTypeDescriptor to override that property
ctd.OverrideProperty(pd2);
}
}
// then we add new descriptor provider that will return our descriptor instead of default
TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(ctd), type);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment