Attributes and classes - c#

I'm searching to how can I know inside an attribute definition if the class I apply the attribute to, has another attribute
Example:
[My1Attribute]
public class MyClass
{
[My2Attribute]
int aux{get;set;}
}
internal sealed class My1Attribute : Attribute
{
public My1Attribute
{
// How can I Know if 'MyClass' has My2Attribute applied ???
}
}

The attribute itself will not know about the class to which it's attached. You will need to use some other service/helper function/whatever to pair them up.
However, you might find the following useful:
public static bool HasAttribute<T, TAttribute>() where TAttribute : Attribute
{
return typeof (T).GetCustomAttributes(typeof (TAttribute), true).Any();
}
Edit: For finding attributes on member fields
/// <summary>
/// Returns all the (accessible) fields or properties that for a given type that
/// have the "T" attribute declared on them.
/// </summary>
/// <param name="type">Type object to search</param>
/// <returns>List of matching members</returns>
public static List<MemberInfo> FindMembers<T>(Type type) where T : Attribute
{
return FindMembers<T>(type, MemberTypes.Field | MemberTypes.Property);
}
/// <summary>
/// Returns all the (accessible) fields or properties that for a given type that
/// have the "T" attribute declared on them.
/// </summary>
/// <param name="type">Type object to search</param>
/// <returns>List of matching members</returns>
public static List<MemberInfo> FindMembers<T>(Type type, MemberTypes memberTypesFlags) where T : Attribute
{
const BindingFlags FieldBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
List<MemberInfo> members = new List<MemberInfo>();
members.AddRange(type.FindMembers(
memberTypesFlags,
FieldBindingFlags,
HasAttribute<T>, // Use delegate from below...
null)); // This arg is ignored by the delegate anyway...
return members;
}
public static bool HasAttribute<T>(MemberInfo mi) where T : Attribute
{
return GetAttribute<T>(mi) != null;
}
public static bool HasAttribute<T>(MemberInfo mi, object o) where T : Attribute
{
return GetAttribute<T>(mi) != null;
}

In this instance, you would need to define your rules about how you determine what members you are going to check. In your example, you're using the attributed decorated on a property, so given that you have an instance of Type for MyClass (e.g. typeof(MyClass)), you can grab the properties:
var property = type.GetProperty("aux", BindingFlags.Instance | BindingFlags.NonPublic);
if (property.IsDefined(typeof(My1Attribute)))
{
// Property has the attribute.
}
(This is assuming you actually want to grab that non-public instance property, if not adjust your BindingFlags).
If you actually want to use the attribute:
var attib = property.GetCustomAttributes(typeof(My1Attribute), false)[0];
// Do something with the attribute instance.

Have you tried Reflection?, plus here's a related question that you might find helpful: How to check if C# class has security attribute used

I am guessing you mean in general find out if any class with MyAttribute1 has My2Attribute (rather than specifically MyClass). The only way I can think of doing it is getting a list of all classes from reflection and iterating through them checking which ones have Attribute1 and then check if they have Attribute2.
I don't think you can do anything clever like automatically retrieve a list of classes with current attribute.

Related

Extend Enum with flag methods?

I have found good examples on how to create extension methods to read out single values from bitwise enums. But now that C# 4 has added the HasFlag method they are really not needed.
What I think would be really helpful though is an extension to SET a single flag!
I have many situations where I need to set the flag values individually.
I want an extension method with this signature:
enumVariable.SetFlag(EnumType.SingleFlag, true);
OR possibly:
enumVariable.SetFlag<EnumType>(EnumType.SingleFlag, true);
Today I found a solution on http://hugoware.net/blog/enums-flags-and-csharp. Thanks Hugo! Excellent code that works fine. I adjusted it slightly and added it to my existing EnumExtender:
public static class EnumExtender
{
/// <summary>
/// Adds a flag value to enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.AddFlag(CustomEnumType.Value1);
/// </summary>
public static T AddFlag<T>(this Enum type, T enumFlag)
{
try
{
return (T)(object)((int)(object)type|(int)(object)enumFlag);
}
catch(Exception ex)
{
throw new ArgumentException(string.Format("Could not append flag value {0} to enum {1}",enumFlag, typeof(T).Name), ex);
}
}
/// <summary>
/// Removes the flag value from enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.RemoveFlag(CustomEnumType.Value1);
/// </summary>
public static T RemoveFlag<T>(this Enum type, T enumFlag)
{
try
{
return (T)(object)((int)(object)type & ~(int)(object)enumFlag);
}
catch (Exception ex)
{
throw new ArgumentException(string.Format("Could not remove flag value {0} from enum {1}", enumFlag, typeof(T).Name), ex);
}
}
/// <summary>
/// Sets flag state on enum.
/// Please note that enums are value types so you need to handle the RETURNED value from this method.
/// Example: myEnumVariable = myEnumVariable.SetFlag(CustomEnumType.Value1, true);
/// </summary>
public static T SetFlag<T>(this Enum type, T enumFlag, bool value)
{
return value ? type.AddFlag(enumFlag) : type.RemoveFlag(enumFlag);
}
/// <summary>
/// Checks if the flag value is identical to the provided enum.
/// </summary>
public static bool IsIdenticalFlag<T>(this Enum type, T enumFlag)
{
try
{
return (int)(object)type == (int)(object)enumFlag;
}
catch
{
return false;
}
}
/// <summary>
/// Convert provided enum type to list of values.
/// This is convenient when you need to iterate enum values.
/// </summary>
public static List<T> ToList<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException();
var values = Enum.GetNames(typeof(T));
return values.Select(value => value.ToEnum<T>()).ToList();
}
/// <summary>
/// Present the enum values as a comma separated string.
/// </summary>
public static string GetValues<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException();
var values = Enum.GetNames(typeof(T));
return string.Join(", ", values);
}
}
I've done something that works for me and very simple. Probably not efficient due to dynamic casting usage. But perhaps you could like it?
public static T SetFlag<T>(this Enum value, T flag, bool set)
{
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
// note: AsInt mean: math integer vs enum (not the c# int type)
dynamic valueAsInt = Convert.ChangeType(value, underlyingType);
dynamic flagAsInt = Convert.ChangeType(flag, underlyingType);
if (set)
{
valueAsInt |= flagAsInt;
}
else
{
valueAsInt &= ~flagAsInt;
}
return (T)valueAsInt;
}
I'm not sure what your question is here, but if you're asking if this is possible, I'd have to say that it isn't, not with this exact syntax.
Enums are value types, and as such, are passed by value. So a method, such as SetFlag, that receives an enum value will receive a COPY of it. Even if it sets a flag, that change would be confined to the method scope, not to the enum that it's called on.
You can pass it to a method with the ref modifier, like this: SetFlag(ref enumVariable, EnumType.SingleFlag) but this isn't supported as an extension method, as far as I know.
What you can do is either create a general enum helper class:
public static class EnumHelper
{
public void SetFlag<TEnum>(ref TEnum enumValue, TEnum flag)
{
enumValue = enumValue | flag;
}
}
or, alternately, create a SetFlag method that returns a new value rather than modifying the existing variable.
public static TEnum SetFlag<TEnum>(this TEnum enumValue, TEnum flag)
{
return enumValue | flag;
}
Maybe not as pretty as you'd hoped but you can do it quite simply :)
enumVariable |= EnumType.SingleFlag;
You maybe need to implement the method for each enum because you can't constraint a enum this way:
public static T SetFlag<T>(this T #this, T flag, Boolean state) where T : enum { ... }
Anyway operator overloads are not allowed in C# on generic types, so you can't use the generic type T without casting.
Solution
So your extension methods must look like this:
public static MyFlag SetFlag(this MyFlag #this, MyFlag flag, Boolean state)
{
return state ? (#this | flag) : (#this & ~flag);
}

protobuf-net inheritance

Marc mentioned on stackoverflow that it will be possible in v2 of protobuf-net to use ProtoInclude attribute (or similar approach) to serialize/deserialize class hierarchy without a need to specify each subtype in the base class. Is this implemented yet? We have a plugin interface that can be derived in external libraries, so there is no way of knowing what the derived types will be. We could maintain unique numbering between types though, but I couldn’t find any examples on the net, short of using ProtoInclude attribute which requires a subtype to be specified.
How would I go about implementing inheritance with protobuf-net like that if I don't know what the subtypes are?
If you can't specify the subtypes in attributes (because it isn't known at compile-time) you have 2 options (both of which only apply to "v2", available as beta):
use a RuntimeTypeModel, rather than the static Serializer methods (which are now just a short-cut to RuntimeTypeModel.Default); tell the model about the inheritance (example below)
add DynamicType = true to the [ProtoMember(...)] in question
The second is not very pure protobuf - it embeds type information, which I don't really love but people just kept asking for. The first is my preferred option. To add subtypes at runtime:
var model = TypeModel.Create();
var type = model.Add(typeof(YourBaseType), true);
var subTypeA = model.Add(typeof(SomeSubType), true);
var subTypeB = model.Add(typeof(SomeOtherSubType), true);
type.AddSubType(4, typeof(SomeSubType));
type.AddSubType(5, typeof(SomeOtherSubType));
the true in the above means "use normal rules to add member properties automatically" - you can also take control of that and specify the properties (etc) manually if you prefer.
Note that a TypeModel should be cached and re-used (not created per object you need to serialize), as it includes some "emit" code to generate methods. Re-using it will be faster and require less memory. The type-model is thread-safe, and can be used to serialize/deserialize multiple streams concurrently on different threads.
To further expand Marc's answer, specifically dealing with RuntimeTypeModel, this is one way to write it:
RuntimeTypeModel.Default[typeof(BaseClass)].AddSubType(20, typeof(DerivedClass));
If you have more classes derived from derived classes, link them like this
RuntimeTypeModel.Default[typeof(DerivedClass)].AddSubType(20, typeof(DerivedFromDerivedClass ));
And so on.
You can then use Serializer.Serialize(file,object), as you would normally with protobuf-net.
This works across projects and namespaces.
By adding helper extension method:
public static class RuntimeTypeModelExt
{
public static MetaType Add<T>(this RuntimeTypeModel model)
{
var publicFields = typeof(T).GetFields().Select(x => x.Name).ToArray();
return model.Add(typeof(T), false).Add(publicFields);
}
}
You can streamline sub-type registration like this:
private static RuntimeTypeModel CreateModel()
{
var model = TypeModel.Create();
model.Add<ExportInfo>();
model.Add<RegistrationInfo>();
model.Add<FactorySetupInfo>()
.AddSubType(101, model.Add<ServiceSetupInfo>().Type)
.AddSubType(102, model.Add<GenericWrapperSetupInfo>().Type)
.AddSubType(103, model.Add<DecoratorSetupInfo>().Type);
return model;
}
I solved this by completely flattening the hierarchy of fields for each ProtoContract. I also assume all fields will be serialized unless [ProtoIgnore] exists and therefore do not decorate fields with [ProtoMember(n)]. It does not need oneOf or [ProtoInclude]. This is what I use, no more scratching my head wondering what went wrong in the numbering etc. Feel free to expand on it to your needs.
A note: it takes any Type decorated with ProtoContract in an Assembly, flattens it's fields, ignores those with [ProtoIgnore], then automatically builds up all the ProtoMembers(n) (so no need for manual numbering).
It also accepts a single Generic Argument Protocol, where you supply the known Generic types e.g MyContract'1 and you supply typeof(MyContract2) such that the concreted type for serializing is MyContract<MyContract2>
Edit: This is a basic example and serves my needs. You may wish to extend it and sort the fields like so, so that you can manage adding new fields and retain backwards compat.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-member-order
To this end you could ignore Proto attributes entirely in the code and replace with DataContract, DataMember etc for discovery and let your contracts be both DataContracts and ProtoContracts with known ordering for both.
/// <summary>
/// <see cref="CompileProtocols(Assembly, Type[])"/>.
/// </summary>
/// <param name="knownGenericArguments"></param>
/// <returns></returns>
public static IEnumerable<Type> CompileProtocols(params Type[] knownGenericArguments)
{
var rv = CompileProtocols(Assembly.GetExecutingAssembly(), knownGenericArguments);
return rv;
}
/// <summary>
/// Compiles protocols that are non generic or take a single generic argument (`1). Single generic argument protocols
/// will be concreted against the knownGenericArguments passed into the method.
/// </summary>
/// <param name="genericArgumentTypes"></param>
public static IEnumerable<Type> CompileProtocols(Assembly inAssembly, params Type[] knownGenericArguments)
{
var runtimeProtocolTypes = new List<Type>();
var assemblyProtocolTypes =inAssembly.GetTypes().Where(t => t.GetCustomAttribute<ProtoContractAttribute>() != null);
foreach(var assemblyProtocolType in assemblyProtocolTypes)
{
if(assemblyProtocolType.IsGenericType == false)
{
runtimeProtocolTypes.Add(assemblyProtocolType);
}
else
{
if (knownGenericArguments.Length > 0)
{
var assemblyTypeGenericArgs = assemblyProtocolType.GetGenericArguments();
if (assemblyTypeGenericArgs.Length == 1)
{
foreach (var knownGenericArgument in knownGenericArguments)
{
var runtimeGenericType = assemblyProtocolType.MakeGenericType(knownGenericArgument);
runtimeProtocolTypes.Add(runtimeGenericType);
}
}
}
}
}
BuildModel(runtimeProtocolTypes);
return runtimeProtocolTypes;
}
/// <summary>
/// Builds and optionally compiles (default=true) the RuntimeTypeModel. In this case it uses the RumtimeTypeModel.Default
/// with a CompileInPlace.
///
/// Note: You might wish to change this to build another model or return a complete Compiled model instead.
/// </summary>
/// <param name="protocolTypes"></param>
/// <param name="compile"></param>
private static void BuildModel(IEnumerable<Type> protocolTypes, bool compile = true)
{
foreach (var protocolType in protocolTypes)
{
int index = 1;
var fields = protocolType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Where(f => f.GetCustomAttribute<ProtoIgnoreAttribute>() == null);
var metaType = RuntimeTypeModel.Default.Add(protocolType);
foreach (var field in fields)
{
metaType.AddField(index, field.Name);
index++;
}
}
if (compile)
{
RuntimeTypeModel.Default.CompileInPlace();
}
}

Conditional "Browsable" Attribute

Is there a way to make a "Browsable" attribute conditional, so the property that applies it will sometimes appear in the properties page and sometimes not?
thanks :)
I'm not sure this applies to your situation, but you can adjust the "Browsable" decoration at run-time by calling the function below.
/// <summary>
/// Set the Browsable property.
/// NOTE: Be sure to decorate the property with [Browsable(true)]
/// </summary>
/// <param name="PropertyName">Name of the variable</param>
/// <param name="bIsBrowsable">Browsable Value</param>
private void setBrowsableProperty(string strPropertyName, bool bIsBrowsable)
{
// Get the Descriptor's Properties
PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(this.GetType())[strPropertyName];
// Get the Descriptor's "Browsable" Attribute
BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);
// Set the Descriptor's "Browsable" Attribute
isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
}
There is no easy way.
You can possibly work this out by implementing ICustomTypeDescriptor. Here is a good article about implementing ICustomTypeDescriptor.
Or you can associate your own ControlDesigner with your class and override the PreFilterProperties method to add or remove properties viewed in the property grid.
Removing certain properties from property grid.
You can do this by providing a custom type-model; at the simplest level, you can provide a custom TypeDescriptor for your type derived from ExpandableObjectConverter, and simply include/exclude the given property at whim - but this only works with PropertyGrid - used by the properties page. A more complex approach is to use ICustomTypeDescriptor / TypeDescriptionProvider - this can then work inside things like DataGridView
John Cummings's solution basically worked for me but had the following two problems due to his introduction of the Generics (which was quite smart though):
1- the version SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable) will fail when a collection is passed as the parameter obj because T, in that case, will be an implementation of IEnumerable (e.g. List, Array etc.) and not the type of the collection that was actually intended.
2- It allows passing in the primitive types as well, which is pointless in this case and will nearly always fail.
Complete revised solution:
So here is the revised solution that tackles these problems and has worked for me:
(I've slightly renamed the methods and the variables)
First of all, the actual method that does the main job of changing the Browsable attribute value:
/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="type">The type that contains the property, of which the Browsable attribute value needs to be changed</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">The new Browsable value</param>
public static void SetBrowsableAttributeOfAProperty(Type type, string propertyName, bool isBrowsable)
{
//Validate type - disallow primitive types (this will eliminate problem-2 as mentioned above)
if (type.IsEnum || BuiltInTypes.Contains(type))
throw new Exception($"The type '{type.Name}' is not supported");
var objPropertyInfo = TypeDescriptor.GetProperties(type);
// Get the Descriptor's Properties
PropertyDescriptor theDescriptor = objPropertyInfo[propertyName];
if (theDescriptor == null)
throw new Exception($"The property '{propertyName}' is not found in the Type '{type}'");
// Get the Descriptor's "Browsable" Attribute
BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
FieldInfo browsablility = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);
// Set the Descriptor's "Browsable" Attribute
browsablility.SetValue(theDescriptorBrowsableAttribute, isBrowsable);
}
Now the variant proposed in John Cummings's solution with <T>:
public static void SetBrowsableAttributeOfAProperty<T>(string propertyName, bool isBrowsable)
{
SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);
}
Now the overload that had the problem no. 1, but the following modification handles it now:
/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="obj">An instance of the type that contains the property, of which the Browsable attribute value needs to be changed.</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">Browsable Value</param>
public static void SetBrowsableAttributeOfAProperty<T>(T obj, string propertyName, bool isBrowsable)
{
if (typeof(T).GetInterface("IEnumerable") != null && typeof(T) != typeof(string)) //String type needs to be filtered out as String also implements IEnumerable<char> but its not a normal collection rather a primitive type
{
//Get the element type of the IEnumerable collection
Type objType = obj.GetType().GetGenericArguments()?.FirstOrDefault(); //when T is a collection that implements IEnumerable except Array
if (objType == null) objType = obj.GetType().GetElementType(); //when T is an Array
SetBrowsableAttributeOfAProperty(objType, propertyName, isBrowsable);
}
else
SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);
and here is a utility function to get all C# system built-in (primitive) types:
public static List<Type> BuiltInTypes
{
get
{
if (builtInTypes == null)
builtInTypes = Enum.GetValues(typeof(TypeCode)).Cast<TypeCode>().Select(t => Type.GetType("System." + Enum.GetName(typeof(TypeCode), t)))
.ToList();
return builtInTypes;
}
}
Usage:
class Foo
{
[Browsable(false)]
public string Bar { get; set; }
}
void Example()
{
SetBrowsableAttributeOfAProperty<Foo>("Bar", true); //works
Foo foo = new Foo();
SetBrowsableAttributeOfAProperty(foo, "Bar", false); //works
List<Foo> foos = new List<Foo> { foo, new Foo { Bar = "item2" } };
SetBrowsableAttributeOfAProperty(foos, "Bar", true); //works now, whereas it would crash with an exception in John Cummings's solution
}
As an improvement on #neoikon's answer above and to avoid the exception Ganesh mentioned in the comments, here is a version that uses generics to get the type:
/// <summary>
/// Set the Browsable property.
/// NOTE: Be sure to decorate the property with [Browsable(true)]
/// </summary>
/// <param name="PropertyName">Name of the variable</param>
/// <param name="bIsBrowsable">Browsable Value</param>
private void SetBrowsableProperty<T>(string strPropertyName, bool bIsBrowsable)
{
// Get the Descriptor's Properties
PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(typeof(T))[strPropertyName];
// Get the Descriptor's "Browsable" Attribute
BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);
// Set the Descriptor's "Browsable" Attribute
isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
}
You can then also add a version that takes an instance:
/// <summary>
/// Set the Browsable property.
/// NOTE: Be sure to decorate the property with [Browsable(true)]
/// </summary>
/// <param name="obj">An instance of the object whose property should be modified.</param>
/// <param name="PropertyName">Name of the variable</param>
/// <param name="bIsBrowsable">Browsable Value</param>
private void SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable)
{
SetBrowsableProperty<T>(strPropertyName, bIsBrowsable);
}
Usage:
class Foo
{
[Browsable(false)]
public string Bar { get; set; }
}
void Example()
{
SetBrowsableProperty<Foo>("Bar", true);
Foo foo = new Foo();
SetBrowsableProperty(foo, "Bar", false);
}
I came across this in search of a way to declare certain members visible or hidden in IntelliSense and be able to change it once for all that needed to be hidden at compile time. I can't tell if that's what you were looking for or not, but I found an answer to my question... figured it couldn't hurt to share.
I set a conditional compilation symbol (found in the Build tab of project properties) IS_VIS (value being true if you want certain members to show, false if your want to hide them) and then:
#if IS_VIS
public const System.ComponentModel.EditorBrowsableState isVis =
ComponentModel.EditorBrowsableState.Always;
#else
public const System.ComponentModel.EditorBrowsableState isVis =
ComponentModel.EditorBrowsableState.Never;
#endif
you then reference the isVis variable in the attribute:
[EditorBrowsable(isVis)]
public string myMethod...
I did this in VB and this was hastily converted to c#. If something doesn't work right, let me know.

Get primitive, complex, ArrayEnumerable types

I have a separate class for each of my database entities and when I create an object of my class to reference the properties of a class it returns a circular reference which contains properties of other entities too that are related via FK ... to remove the circular reference I want to first make a copy of the object through "context proxy object" copy and then get the primitive, complex, arrayEnumerable types of that object and strip off these types from the object and then the object get returned by web service....
Sounds like a recursive shallow clone. I've used the following but only one level deep.
public static class EntityBaseExtensions
{
/// <summary>
/// Description: Creates a non-recursive shallow copy of an entity, only including public instance properties decorated with ColumnAttribute.
/// This will return an object without entity references.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns>A non-recursive shallow copy of a LINQ entity</returns>
public static T ShallowClone<T>(this T source) where T : EntityBaseClass
{
// create an object to copy values into
T destination = Activator.CreateInstance<T>();
// get source and destination property infos for all public instance
PropertyInfo[] sourcePropInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] destinationPropInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo sourcePropInfo in sourcePropInfos)
{
if (Attribute.GetCustomAttribute(sourcePropInfo, typeof(ColumnAttribute), false) != null)
{
PropertyInfo destPropInfo = destinationPropInfos.Where(pi => pi.Name == sourcePropInfo.Name).First();
destPropInfo.SetValue(destination, sourcePropInfo.GetValue(source, null), null);
}
}
return destination;
}
}

C# reflection, cloning

Say I have this class Myclass that contains this method:
public class MyClass
{
public int MyProperty { get; set; }
public int MySecondProperty { get; set; }
public MyOtherClass subClass { get; set; }
public object clone<T>(object original, T emptyObj)
{
FieldInfo[] fis = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object tempMyClass = Activator.CreateInstance(typeof(T));
foreach (FieldInfo fi in fis)
{
if (fi.FieldType.Namespace != original.GetType().Namespace)
fi.SetValue(tempMyClass, fi.GetValue(original));
else
fi.SetValue(tempMyClass, this.clone(fi.GetValue(original), fi.GetValue(original)));
}
return tempMyClass;
}
}
Then this class:
public class MyOtherClass
{
public int MyProperty777 { get; set; }
}
when I do this:
MyClass a = new MyClass {
MyProperty = 1,
MySecondProperty = 2,
subClass = new MyOtherClass() { MyProperty777 = -1 }
};
MyClass b = a.clone(a, a) as MyClass;
how come on the second call to clone, T is of type object and not of type MyOtherClass
Your second (recursive) call to clone passes the result of GetValue as the second argument, which is of type object, and hence T is object.
i.e.
fi.SetValue(tempMyClass, this.clone(fi.GetValue(original), fi.GetValue(original)));
The result of GetValue on a FieldInfo is an object.
Given that you pass the same thing twice in all cases, the design of the clone method is possibly wrong. You probably don't need generics there. Just use obj.GetType() to get the type information of the second argument (if indeed you really need a second argument).
It would make more sense to constrain the return type using generics, so that the cast isn't necessary on the calling side. Also you could make Clone into an extension method so it could apply to anything.
On the other hand, the thing you're trying to do (an automatic deep clone) is unlikely to be generally useful. Most classes end up hold references to things that they don't own, so if you clone such an object, you end up accidentally cloning half of your application framework.
Try this:
public static class Cloner
{
public static T clone(this T item)
{
FieldInfo[] fis = item.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object tempMyClass = Activator.CreateInstance(item.GetType());
foreach (FieldInfo fi in fis)
{
if (fi.FieldType.Namespace != item.GetType().Namespace)
fi.SetValue(tempMyClass, fi.GetValue(item));
else
{
object obj = fi.GetValue(item);
fi.SetValue(tempMyClass, obj.clone());
}
}
return (T)tempMyClass;
}
}
MyClass b = a.clone() as MyClass;
Best way to clone an instance of a class is to create a delegate to do it. Indeed, delegate produced by linq expression can access private/internal/protected and public fields. Delegate can be created only once. Keep it in static field in generic class to take benefit of generic lookup resolution instead of dictionary
/// <summary>
/// Help to find metadata from expression instead of string declaration to improve reflection reliability.
/// </summary>
static public class Metadata
{
/// <summary>
/// Identify method from method call expression.
/// </summary>
/// <typeparam name="T">Type of return.</typeparam>
/// <param name="expression">Method call expression.</param>
/// <returns>Method.</returns>
static public MethodInfo Method<T>(Expression<Func<T>> expression)
{
return (expression.Body as MethodCallExpression).Method;
}
}
/// <summary>
/// Help to find metadata from expression instead of string declaration to improve reflection reliability.
/// </summary>
/// <typeparam name="T">Type to reflect.</typeparam>
static public class Metadata<T>
{
/// <summary>
/// Cache typeof(T) to avoid lock.
/// </summary>
static public readonly Type Type = typeof(T);
/// <summary>
/// Only used as token in metadata expression.
/// </summary>
static public T Value { get { throw new InvalidOperationException(); } }
}
/// <summary>
/// Used to clone instance of any class.
/// </summary>
static public class Cloner
{
/// <summary>
/// Define cloner implementation of a specific type.
/// </summary>
/// <typeparam name="T">Type to clone.</typeparam>
static private class Implementation<T>
where T : class
{
/// <summary>
/// Delegate create at runtime to clone.
/// </summary>
static public readonly Action<T, T> Clone = Cloner.Implementation<T>.Compile();
/// <summary>
/// Way to emit delegate without static constructor to avoid performance issue.
/// </summary>
/// <returns>Delegate used to clone.</returns>
static public Action<T, T> Compile()
{
//Define source and destination parameter used in expression.
var _source = Expression.Parameter(Metadata<T>.Type);
var _destination = Expression.Parameter(Metadata<T>.Type);
//Clone method maybe need more than one statement.
var _body = new List<Expression>();
//Clone all fields of entire hierarchy.
for (var _type = Metadata<T>.Type; _type != null; _type = _type.BaseType)
{
//Foreach declared fields in current type.
foreach (var _field in _type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
//Assign destination field using source field.
_body.Add(Expression.Assign(Expression.Field(_destination, _field), Expression.Field(_source, _field)));
}
}
//Compile expression to provide clone method.
return Expression.Lambda<Action<T, T>>(Expression.Block(_body), _source, _destination).Compile();
}
}
/// <summary>
/// Keep instance of generic definition of clone method to improve performance in reflection call case.
/// </summary>
static private readonly MethodInfo Method = Metadata.Method(() => Cloner.Clone(Metadata<object>.Value)).GetGenericMethodDefinition();
static public T Clone<T>(T instance)
where T : class
{
//Nothing to clone.
if (instance == null) { return null; }
//Identify instace type.
var _type = instance.GetType();
//if T is an interface, instance type might be a value type and it is not needed to clone value type.
if (_type.IsValueType) { return instance; }
//Instance type match with generic argument.
if (_type == Metadata<T>.Type)
{
//Instaitate clone without executing a constructor.
var _clone = FormatterServices.GetUninitializedObject(_type) as T;
//Call delegate emitted once by linq expreesion to clone fields.
Cloner.Implementation<T>.Clone(instance, _clone);
//Return clone.
return _clone;
}
//Reflection call case when T is not target Type (performance overhead).
return Cloner.Method.MakeGenericMethod(_type).Invoke(null, new object[] { instance }) as T;
}
}
First of all I agree that clone method should be static, but I don't think that
object tempMyClass = Activator.CreateInstance(typeof(T));
is a good idea. I think that better way is to use type of original and get rid of emptyObject parameter at all.
object tempMyClass = Activator.CreateInstance(original.GetType());
Also you have to GetFields on original not on this.
So my method would be
public static T clone<T>(T original)
{
T tempMyClass = (T)Activator.CreateInstance(original.GetType());
FieldInfo[] fis = original.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fi in fis)
{
object fieldValue = fi.GetValue(original);
if (fi.FieldType.Namespace != original.GetType().Namespace)
fi.SetValue(tempMyClass, fieldValue);
else
fi.SetValue(tempMyClass, clone(fieldValue));
}
return tempMyClass;
}
Note that I use original.GetType() anyway as inner call would have type T=Object anyway. Used generic type is determined at compilation time and it would be Object as return type of fi.GetValue.
You can move this static method to some static helper class.
As a side note I'd like to say that this implementation of "deep" clone will not work properly if there is some collection-type field (or any standard mutable composite field) in one of classes in your namespace.
I tried to clone an entity framework object with the examples posted here but nothing worked.
I made an extension method with a different way and now I can clone EF objects:
public static T CloneObject<T>(this T source)
{
if (source == null || source.GetType().IsSimple())
return source;
object clonedObj = Activator.CreateInstance(source.GetType());
var properties = source.GetType().GetProperties();
foreach (var property in properties)
{
try
{
property.SetValue(clonedObj, property.GetValue(source));
}
catch { }
}
return (T)clonedObj;
}
public static bool IsSimple(this Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple(type.GetGenericArguments()[0]);
}
return !type.IsClass
|| type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
I didn't check for the array cases but you can add some code for that too (like in this link):
else if (type.IsArray)
{
Type typeElement = Type.GetType(type.FullName.Replace("[]", string.Empty));
var array = obj as Array;
Array copiedArray = Array.CreateInstance(typeElement, array.Length);
for (int i = 0; i < array.Length; i++)
{
// Get the deep clone of the element in the original array and assign the
// clone to the new array.
copiedArray.SetValue(CloneProcedure(array.GetValue(i)), i);
}
return copiedArray;
}

Categories