Distinguish class property types through reflection - c#

I have a Rectangle class
public class Rectangle : Base, IRectangle
{
public IDimension dimension { get; set; }
public Position position { get; set; }
public String color { get; set; }
public int ID { get; set; }
public override String ToString()
{
return base.ToString(this);
}
}
Are there any way to distinguish through reflection types of properties which defined on Rectangle class?
How can I understand ID is struct or dimension is Interface? And Both String and Position are class but String is build in class, Position is Custom class.

You can use this property:
typeof(T).IsPrimitive
To check if a type is primitive or non-primitive
This one:
typeof(T).IsInterface
To check if a type is an interface or not.
This is how you check is a type is a struct or not:
typeof(T).IsValueType
In case you are truly looking only for "pure" structs (not just value types in general) then:
typeof(T).IsValueType && !typeof(T).IsEnum;

var prop = typeof(Rectangle).GetProperty("ID");
if(prop.PropertyType.IsValueType)
{
..
}
prop = typeof(Rectangle).GetProperty("dimension");
if(prop.PropertyType.IsInterface)
{
...
}
prop = typeof(Rectangle).GetProperty("color");
if(prop.PropertyType.IsClass)
{
...
}
As you might have noticed Type class contains several properties that you can determine whether the type is a value type,or interface or class etc.
To determine whether the class type is built-in type or custom type, I think you can check whether type's Assembly is loaded from the GAC (Global assembly cache) or not.It's not the best solution but I don't know another way.
if(prop.PropertyType.Assembly.GlobalAssemblyCache)
{
// built-in type..
}

the above answer are good.
BUT
if you something that is extensible, you can create your own custom Custom Attributes and use reflection on that Type.
For example, you can create attribute that's contain how to print properties or how to validate them, get those all with reflection.
we use this way to create protocol parser, where each properties we define the order in the protocol, the length, and the validation - But again - this can be over killer for you

Related

Exclude complex property with reflection get properties [duplicate]

Is it possible when looking at a class' properties to detect if any of them is a reference type.
Take below as an example:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProgrammeClient
{
public int Id { get; set; }
public bool IsActive { get; set; }
public IClient Client { get; set; }
}
ProgrammeClient: -
Id and IsActive are properties but Client is a reference type. Is there a way of detecting this?
Many thanks,
Kohan.
Addendum
The reason i ask is: I am using a mapper that checks types are the same before matching property names and copying the values. My hope is to detect classes and override the type matching and simply copy the classes properties if the THEY type match.
Well, it sounds like you may be trying to detect the difference between a value type and a reference type. You can find that out using Type.IsValueType... but be aware that value types can easily have properties too. (Think about DateTime for example.) Also, some types which you may want to regard as "not objects" are reference types - string being a prime example.
Another option would be to use Type.IsPrimitive - is that what you're looking for? If so, you should be aware that decimal, DateTime and string are not primitive types.
If you can describe exactly what makes a type an "object" in your way of thinking (or rather, in whatever way makes a semantic difference in what you're trying to do with your type). I suspect you don't currently have a very clear set of criteria - coming up with those criteria may well clarify other aspects of your current task, too.
You can use a little reflection to see if a property is a value type or a class type. Class is probably what you mean by "object". All types in .NET derive from the object type.
Client.GetType().IsClass
Or you can loop through all properties and see which are compound
foreach(var p in ProgrammeClient.GetType().GetProperties())
{
if(p.PropertyType.IsClass) Console.WriteLine("Found a class");
}
Check if the type is a string and check if it is a class.
public static bool IsNonStringClass(this Type type)
{
if (type == null || type == typeof(string))
return false;
return typeof(Type).IsClass;
}
All properties in your example return objects, as everything is an object in .NET; int and bool are objects. If you mean a reference type, as opposed to value types, then you can do the following:
foreach (PropertyInfo pi in typeof(Client).GetProperties()) {
if (pi.PropertyType.IsClass) {
// reference type
// DoMyFunkyStuff
}
}
You can enumerate the properties via Reflection, and check them:
bool ContainsOnlyValues() {
return typeof(ProgrammeClient).GetProperties().All(x => x.PropertyType.IsValueType);
}
The Type.IsvalueType property can reveal this.
Id.GetType().IsValueType
This will be True for Id, false for a class
If using TypeSupport nuget package you can simply do:
typeof(ProgrammeClient).GetExtendedType().IsReferenceType;
TypeSupport does inspection and provides deeper insight on the capabilities of a given type, handling things like strings, enums etc and makes it easier to code these types of things.

Insert object into value with different base type (inherited) c#

So I have have an object of type SvgElement that contains a value of SvgPath(which inherits SvgElement). Here's the code.
SvgElement createdElement;
//other operations. createdElement now has other data of SvgPath
if (createdElement.GetType() == typeof(SvgPath) & createdElement.ElementName == "path" && storedValue != "")
createdElement.PathData = SvgPathBuilder.Parse(storedValue);
return createdElement
(Note: this is being done in unity, .net 2.0 must be taken into consideration as Unity takes offence to System.Linq)
Now SvgPathBuilder.Parse takes a string and returns an object of type SvgPathSegmentList into PathData. PathData is normally a variable within SvgPath, but I modified SvgElement to temporarily take the value so I would know if something else I was testing would work.
Now that I've given you the background info..How do I (generic code- Type T stuff) write it so that SvgPathBuilder.Parse will be stored in SvgPath.PathData rather than the inherited base SvgElement's PathData?
(not sure if title fits question, please advise)
You can cast the element to SvgPath:
(createdElement as SvgPath).PathData = SvgPathBuilder.Parse‌​(storedValue);
It is not very clear what are you trying to achieve from mere description, but consider following design, which still need further changes to suit exact requirements
Important details:
SvgElement made abstract with abstract property that needs to be implemented by the Child, i.e. SvgPath
Generic constraints used in the TestSVG to ensure, we always supply the correct class or its derived version, in this class you can implement the filling of property PathData
public abstract class SvgElement
{
public abstract List<SvgPath> PathData { get; set;}
}
public class SvgPath : SvgElement
{
public override List<SvgPath> PathData { get; set;}
}
public class TestSvg<T> where T:SvgElement
{
}

C# How to use get, set and use enums in a class

I have a program where I use a class store settings. I need it to use set and get functions to change and store settings. I have tried this, and I don't get it to work. Can anyone help me with this one?
private enum _Difficulty { Easy, Normal, Hard };
public void SetDifficulty(Difficulty)
{
_Difficulty = Difficulty;
}
public enum GetDifficulty()
{
return _Difficulty;
}
Is there no way to use enums in a class with get and set?
I also need this with bool and int.
There are several things wrong here:
Your enum is private, but your methods are public. Therefore you can't make your methods return type be the enum type, or have parameters with that type
Your SetDifficulty method has a parameter of just Difficulty - is that meant to be the parameter name or the type?
Your SetDifficulty method is trying to set the type rather than a field
Your GetDifficulty method is trying to use enum as a return type, and is then returning a type rather than a field
Basically, you seem to be confused about what your enum declaration is declaring - it's not declaring a field, it's declaring a type (and specifying what the named values of that type are).
I suspect you want:
// Try not to use nested types unless there's a clear benefit.
public enum Difficulty { Easy, Normal, Hard }
public class Foo
{
// Declares a property of *type* Difficulty, and with a *name* of Difficulty
public Difficulty Difficulty { get; set; }
}
You can use get/set methods if you really want to make your code look like Java instead of C#:
public enum Difficulty { Easy, Normal, Hard }
public class Foo
{
private Difficulty difficulty;
public void SetDifficulty(Difficulty value)
{
difficulty = value;
}
public Difficulty GetDifficulty()
{
return difficulty;
}
}
Once you specify an enum using the enum keyword, that enum acts as a type, like a class or struct would.
Here's how you'd implement a property with a custom enum:
public enum _Difficulty { Easy, Normal, Hard };
public _Difficulty Difficulty { get; set; }
You code tries to assign Difficulty a value, when in fact Difficulty is the name of the enum type. I would encourage use of getters and setters as properties instead:
public enum Difficulty { Easy, Normal, Hard };
private Difficulty _difficulty;
public Difficulty CurrentDifficulty
{
get { return _difficulty; }
set { _difficulty = value; }
}
This way you can add additional code in the setter for special conditions. To use it you simply do the following:
//set
CurrentDifficulty = Difficulty.Easy;
//get
Difficulty theDifficulty = CurrentDifficulty;
The enum you want to use needs to be public. You also need an instance of that enum to store the value you're setting, you're currently setting it to your enum's declaration. Then you want to use the same enum type for what your class stores and what you pass in.
public enum Difficulty { Easy, Normal, Hard };
public Difficulty { get; set; }
There are a number of issues here:
Your enum is private, so nothing will be able to call SetDifficulty to provide it with a value from that enum. Indeed, the compiler won't allow this.
The argument to SetDifficulty is just a type, it also needs a variable name. Also a compiler error.
You're trying to get/set the value of the enumeration itself, rather than a class-level variable of the type of the enumeration. This too won't compile.
It looks like you want to do this:
public enum Difficulty { Easy, Normal, Hard }
public Difficulty DifficultySetting { get; set; }
Note that I had to change the name of the property to DifficultySetting because it conflicts with the enum name. Yours used an underscore, which would also solve that problem. However I always found that underscores are for private members and if you want consuming code to use this enum then it would need to be public. Decorating a public member with things like underscores distracts from the semantics of the name itself. In any event, the semantics are up to your personal preference, so you can modify these names as you see fit.
I'm not sure you are using them correctly. This might help...
private enum Difficulty { Easy, Normal, Hard };
private Diffuculty theDifficulty;
public void SetDifficulty(difficulty d)
{
theDifficulty = difficulty;
}
public Difficulty GetDifficulty()
{
return theDifficulty;
}
An enum is a type not a variable. Something like this would work:
public enum Difficulty { Easy, Normal, Hard };
private Difficulty _Difficulty;
public void SetDifficulty(Difficulty difficulty )
{
_Difficulty = Difficulty;
}
public Difficulty GetDifficulty()
{
return _Difficulty;
}
or more succinctly as an Auto Property:
private Difficulty Difficulty {get; set;}
Note that the enum has to be public if you want it to be accessible from public methods.

Should the TypeIds of two attributes which are semantically identical be different or the same?

MSDN states of the property TypeId that:
As implemented, this identifier is merely the Type of the attribute. However, it is intended that the unique identifier be used to identify two attributes of the same type.
Is the intended use however, to distinguish between individual attribute instances (e.g. those associated with different instances of the class to which they are applied) or between attributes which have the same type but due to their property values are semantically different?
For example, say I had the following:
public sealed class AmpVolume : System.Attribute
{
public int MaxVolume { get; set; }
public AmpVolume(int maxvolume)
{
MaxVolume = maxvolume;
}
}
[AmpVolume(11)]
public class SpinalTapGuitarAmp
{
}
[AmpVolume(11)]
public class SpinalTapBassAmp
{
}
[AmpVolume(10)]
public class RegularAmp
{
}
Should I implement TypeId as
get
{
return (object)this; //TypeId identifies every individual instance of the attribute
}
Or
get
{
return (object)MaxVolume; //If we compare two AmpVolume attributes, they should be the same if the volume is the same, right?
}
The TypeId property is used to distinguish between instances of the same attribute on the same member. Meaning, it's required to implement it only when the attribute is decorated with AttributeUsageAttribute which declares AllowMultiple=true.
For example, if you'd decorate a class or method with multiple AmpVolume attributes, then the TypeId will distinguish between those instances.
You can find a hint on the property in the note at this MSDN link for GetAttributes method.

Property type depends on enum value

How should i implement, in C#, a class containing a property with the type of something and then that something example :
public class MyObject{
public someEnum e { get; set;}
public Object ObjectDependentOnE { get; set; }
}
I want to be able to return the right type for my object which depends on my enum.
for example if e = 1, my object is of type T1...
or maybe I trying to do somethng wrong
any idea?
I am unsure of what you are really trying to do, but it appears that generics is what you are looking for:
public class MyObject<T>
{
public T SomeProperty{get;set;}
}
You can constraint T to classes that implement a given interface.
Usage would be:
MyObject<SomethingClass> something = new MyObject<SomethingClass>;
I'm not sure what your use case would be - more information might help answer this better, but from my guess, you may want to consider making a factory class instead. Something like:
class MyClass
{
public SomeEnum E { get; set; }
// This might be better as : public Object GetTheObject(SomeEnum E) and eliminating the above property
public Object GetTheObject()
{
switch(this.E)
{
case E.Something:
return new MySomethingObject(); // Or return an instance that already exists...?
default:
return new MyDefaultObject();
}
}
}
This could also be a property with a getter and setter, and get and set the specific object type.
However, I recommend considering rethinking the approach - this seems like a very error-prone design, since it has no type safety at compile time, and is very confusing from the consumer's POV.

Categories