Get the CustomAttributes of a specific member - c#

Is there any way to get the custom attributes of a specific object I am receiving in a method?
I do not want nor can to iterate over Type.GetMembers() and search for my member. I have the object, which is also a member, that has the attribute.
How do I get the attribute?
class Custom
{
[Availability]
private object MyObject = "Hello";
private void Do(object o)
{
//does object 'o' has any custom attributes of type 'Availability'?
}
//somewhere I make the call: Do(MyObject)
}

No. Objects don't have attributes - members do. By the time you're in the "Do" method, there's no record of the fact that you called Do(MyObject) vs Do(MyOtherFieldWhichHasTheSameValue).
If you need to look up the attributes on a member, you'll basically have to pass in the relevant MemberInfo, not what it happens to evaluate to.

You cannot do this without at least 1 Reflection call. After that, save the value somehow.
Example:
abstract MyBase
{
public string Name;
protected MyBase()
{
//look up value of Name attribute and assign to Name
}
}
[Name("Foo")]
class MyClass : MyBase
{
}

Related

Validation against the non generic attribute of a generic type

I want to validate a class, that has a property of a generic type:
class Foo
{
[ValidHistoryDate]
public MyType<string> bar;
[ValidHistoryDate]
public MyType<int> baz;
[ValidHistoryDate]
public MyType<float> bat;
}
class MyType<T>
{
public string date;
public T property;
}
The generic type also contains a date, attribute (string), that should be validated against a valid date, so I wrote this function to do this:
public class ValidHistoryDateAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null)
return true;
var v = (List<MyType<object>>)value;
bool valid = true;
foreach (var f in v)
{
if (!Regex.Match(f.Date, #"^[0-9]{2}\.[0-9]{2}\.[0-9]{4}$").Success)
valid = false;
}
return valid;
}
}
The validation does not care about the property "property", but it should care about the string.
Unfortunately the cast fails:
var v = (List<MyType<object>>)value;
I mean: Of course it does, because "object" is not the real type. I want to use the validation attribute for all types and in the validation I actually do not even care about "property".
Any way to solve this in a nice way? I do not want to add a ValidHistoryDateAttribute for every possible type.
If I were to do this I would add a non-generic base type into your code:
public class ValidatableObject
{
public string date;
}
And then my class would be:
class MyType<T> : ValidatableObject
{
public T property;
}
Your validation code would then refer to the base class which makes things a lot simpler.
It looks like you are actually trying to cast something of type List<GenerericHistory<T>> which will run into Variance problems. If you are assuming you are using my base class the incoming item cannot easily be converted to List<ValidatableObject> - to see why consider that the actual list should only allow adding of GenerericHistory<T> (where T is a specific type) objects whereas a List<ValidatableObject> would allow adding of GenerericHistory<T> objects of any type. Thus the cast is not allowed.
If you were to change the list to an IEnumerable<GenerericHistory<T>> then you would be able to cast to IEnumerable<ValidatableObject>. The reason is that this time we have a readOnly object so all we are doing is getting out objects of type ValidatableObject and since know that the actual class will only ever return GenerericHistory<T> (for specific T) we also know it always returns of type ValidatableObject and thus this time the cast is allowed.
The last bit is based partly on speculation since your code seems to be inconsistent with regards to the use of List<T> in your code. I assume the validator is correct that a property on your validatable object is a list but obviously I have no idea if that List can be changed, etc.

Initialize Property of Generic Type

I have read multiple posts but haven't found an appropriate answer for my problem.
But there has to be one. So please be patient if this post really is an duplicate.
I try to initialize a Property of a generic type implementing a generic interface.
My interface looks basically like this:
public interface IMyInterface<TType> : IMyInterface
{
TType Value {get; set;}
// ... and some more ...
}
public interface IMyInterface
{
SetValue(string value);
}
I have multiple Classes implementing IMyInterface without knowing them
at the piece of code, where I need to set the value.
Is it possible to inizialize the "Value"-Property without using the Name of the property?
(Is there a "nice" way to do this?) - It isn't possible to use SetValue< TType >
void SetValue(object obj, string value)
{
// object obj implements IMyInterface<???>
PropertyInfo valueInfo = typeof(obj).GetType().GetProperty("Value")
valueInfo.SetValue(obj, Activator.CreateInstance(valueInfo.PropertyType))
((IMyInterface)obj).SetValue(value);
}
Thanks in advance.
EDIT: - removed -
EDIT 2:
This structure is given:
public Interface IGeneric<TType> : INonGeneric
{
TType Value2 {get;}
}
public Interface INonGeneric
{
object Value1 {get;}
}
using "Value1" from reflection is really easy:
INonGeneric myObject = (INonGeneric)givenObject;
doSomething(myObject.Value1)
if i need to access "Value2" it isn't that easy. As one can see in my first example I had to use the following construct which not seems to be the best way to access "Value2", because the properties name is hardcoded.
PropertyInfo valueInfo = givenObject.GetType().GetProperty("Value2");
object value = (object)valueInfo.GetValue(givenObject);
Is there any better solution?
If i got you right you have and instance that implements IGeneric, and you want to access the property Value2 (which has a generic return type).
The thing is, Generics are for compile time type safety. You cannot cast your object to IGeneric<...> if you don't know the type parameter. So why do you want to use Generics anyway if you don't know the type parameter?
There is a solution for this "problem", it is the same as IEnumerable and IEnumerable< T> uses. it can look something like this:
public interface INonGeneric
{
object Value {get; }
}
public interface IGeneric<T>
{
T Value { get; }
}
public class Magic : INonGeneric, IGeneric<string>
{
object INonGeneric.Value { get { return this.Value; } }
public string Value { get { return "test"; } }
}
You can now use cast the Object to INonGeneric if you don't use the type parameter, or use the Generic implementation if you know the type parameter at compile time.
But if you want to access a property of a generic type (you have no control over) without knowing the type parameter you will not get around either reflection or dynamic.
The dynamic solution can look like this:
dynamic generic = givenObject;
object value2 = generic.Value2;

Checking Type Inside Collection in C#

I am kind of new to C# and not sure about the following:
I have a parameter defined as follows:
public Collection<object> InputObject
{
get { return inputObject; }
set { inputObject= value; }
}
private Collection<object> inputObject;
As you can see, the object is a collection of objects since I am expecting different types.
When later I want to check the type, what is the right way?
I tried this:
if (inputObject is Collection<MyDefinedObject>)
{
}
but I get an underlined warning that the given expression is never of the expected type. What is the right way to check for a type within a collection?
Thanks
You have a collection of Object
When you write
Collection<object>
that means you are defining a collection that can contain any object.
When you do that, you can then do something like
inputObject.Add(new MyDefinedObject());
inputObject.Add(new StringBuilder()));
and you end up with different types in your collection.
Checking specific elements of your collection
If you want to test the type of a specific object in that collection you could so something like
Type t = inputObject[0].GetType();
or
if (inputObject[0] is MyDefinedObject)
The code
if (inputObject is Collection<MyDefinedObject>)
will never be true because you already defined
private Collection<object> inputObject;
meaning you defined the type of the collection inputObject to be Collection<object>
What if I want everything in the collection to be MyDefinedObject?
Based on your comments below your question, this is what you really want...
private Collection<MyDefinedObject> inputObject;
The Error Message You are Getting
but I get an underlined warning that the given expression is never of the expected type
That is because inputObject is of type Collection<object>, which is never of type Collection. That's like saying an apple is never a banana.
A Better Approach
If you are using generics and receiving a generic collection, why not create a generic function to process that collection too?
private void ProcessCollection<T>(Collection<T> inputObject)
{
}
// Somewhere else in your code...
Collection<MyDefinedObject> inputObject = // Initialize this however you do now
ProcessCollection<MyDefinedObject>(inputObject);
Since your Collection<> contains object, the collection has (in essence) no type. You either give the collection an actual type, or you check the items IN the collection for a type.
All object inherits the base class object, then you can use :
if(InputObject[0].GetType()==typeof(string)){
//string is an example and 0 can be replaced with a index
}
to know which type is each object
You are going to need to check all. The collection is defined as object
foreach (object obj in InputObject)
{
obj.gettype();
if (obj is DocFieldEnumHierTwoSpeedLoader) x= 5;
}
Perhaps this is what you want:
var defined = InputObject.OfType<MyDefinedObject>();
var other = InputObject.OfType<MyOtherDefinedObject>();
bool hasDefined = defined.Any();
bool hasOther = other.Any();
You say that the inputObject property can contain collections whose collection type can vary from time to time. There are two solutions:
1) If the type of the collection's elements is always the same for a given instance of the type that defines the property, make that type generic:
public class MyClass<T>
{
public Collection<T> InputObject
{
get { return inputObject; }
set { inputObject= value; }
}
private Collection<T> inputObject;
}
If the same instance of the property could hold collections with varying element types, then declare the field as object, or, perhaps better, as a non-generic interface type:
public class MyClass
{
public ICollection InputObject
{
get { return inputObject; }
set { inputObject= value; } // you should add some type checking here
//to make sure an invalid collection type isn't passed in
}
private ICollection inputObject;
public Collection<T> GetTypedCollection<T>()
{
return (Collection<T>)inputObject;
}
}
The GetTypedCollection method requires that you know at compile time what the collection's type is; if that's not possible, you'll need to post more sample code so we can suggest a solution.

C# generic class accepting a inherited type.

**Preface I'm very new to generics. I have a class I created called Geno. My Peno class simply contains a string Name property. I'm wondering why I cannot call T.Name from within a method on this class. How would I access the properties on T? Any good resources on how this works?
public class Geno<T> where T : Peno
{
}
public string GetName()
{
return T.Name;
}
Is your Name property an instance property or a static property? If it's a static property, you don't get polymorphism anyway - you could just call Peno.Name.
If it's an instance property, you need an instance on which to call it. For example:
public class Geno<T> where T : Peno
{
private readonly T value;
public Geno(T value)
{
this.value = value;
}
public string GetName()
{
return value.Name;
}
}
If this doesn't help, please give a more complete example of what you're trying to do.
T is the type Peno. So what you try to do is Peno.Name, which is probably not what you want. Something like this would work:
public string GetName(T t)
{
return t.Name;
}
Static properties does not support inheritence. Hence you can just call Peno.Name rather than going for T.
If in your case you want to access a normal property, you need to create an instance of T which will let you call its property Name.
T is a Generic Type Parameter, not a parameter being passed into the class that is using T.
A Good example of this is List<T> you say this is a List, which means you are creating a list that contains object of the type of String.

Create a property that accepts a different type than it returns

I have a public method in a class. I would like to make this private and use a property to expose the method. The problem is that my method accepts an integer parameter and returns a boolean. In my experience a property has to accept and return the same type. What is the best practice to encapsulate this method and expose it using a property?
You shouldn't be using properties this way. Properties are used to wrap get_ and set_ calls to an appropriate backing field and expose them as a single member. The set_ method that is generated internally is void and accepts an instance of the property type as its only argument.
If what you are trying to achieve requires a method, then expose a method. The only solution you could possibly use otherwise would be to use object.
If the value passed in isn't the same as the value returned, then it's not a property. If you go down this route you'll be creating confusion for anyone who needs to call your code, or maintain it in the future.
The only solution I can think of, and a bad one at that, is to declare the property to be of type object.
What is the best practice to encapsulate this method and expose it using a property?
Does it have to be the same property? Could you have something similar to:
private Type2 _valueThatIsStoredAsAResultOfCallMethod;
private Type2 CallMethod(Type1 value)
{
// Whatever logic is required here to take a value of Type1 and
// get a value of Type2 from it
return value.ToType2();
}
public Type1
{
set
{
// value is of type Type1
_valueThatIsStoredAsAResultOfCallMethod = CallMethod(value);
}
}
public Type2
{
get
{
return _valueThatIsStoredAsAResultOfCallMethod;
}
}
public bool MyProp
{
get;
private set;
}
public int MyProp_AsInt
{
set
{
MyProp = (value > 0) ? true : false;
}
}
Your function's body can replace the above 'set'.
I just put some sample code there.
Make sure you assign the return val of your function to MyProp.
full code
public class MyClass
{
public bool MyProp
{
get;
private set;
}
public int MyProp_AsInt
{
set
{
MyProp = (value > 0) ? true : false;
}
}
}
public class Program
{
static void Main(string[] args)
{
MyClass o = new MyClass();
o.MyProp_AsInt = 1;
System.Console.WriteLine("{0}", o.MyProp);
o.MyProp_AsInt = 0;
System.Console.WriteLine("{0}", o.MyProp);
string line = System.Console.ReadLine();
}
}
Well, generally speaking, it's bad practice to call a method via a property (or do anything complicated in a property) as it's not what the user of the class would expect to happen. The expected behaviour being getting a value.
I would just expose the method.
A method that takes a parameter and returns a value doesn't translate well into a property, regardless of the types it uses.
The method accepts the parameter, then returns the result, while a parameter either accepts a value or returns a value, not both in the same operation. If you would have to use the property by first setting the value, then reading the value, that would be very counter intuitive. It's simply not at all how you normally use a property.
There is no best practice for doing this because it's a bad practice.
If you had two covariant types as your accept/return, you could refer to them by their lowest common ancestor, but I'd still be wary.

Categories