Add dynamic property to .NET classes - c#

Is it possible to add my own custom property to any type of object?
In this example the object is List but I mean for any kind of object (.NET or custom ones).
For example extend List<string> to add an extra property called MyProperty:
List<string> myList = new List<string>();
myList.MyProperty = "some value";
then call a method ProcessList(List<string> list):
ProcessList(myList);
public void ProcessList(List<string> list)
{
// get the custom property value
string myprop = list.MyProperty.ToString();
....................
do other work
}

No. There is no "extension property" implementation in .NET. Extension methods are more of a compiler trick, and only work as static methods because they do not require their own state (at least should not).
A property would require a backing field, which would require other functionality in order to implement properly.
Note that certain frameworks do support this. For example, if your object derives from DependencyObject, you could use Attached Properties to implement this functionality.

Not the way you're describing. Extension methods are probably the closest you'll get.
public static class QueryExtensions
{
public static bool HasMapping(this Demand role)
{
return role.DemandMappings.Count > 0;
}
}
You would use the above example like this:
var role = GetDemand(Request.QueryString["id"]);
if (role != null)
{
var mapped = role.HasMapping();
}

Related

Usage of C# attribute methods

In C#, what is the purpose of methods declared in attributes and how are they used?
As an example, have a look at the attribute MaxLengthAttribute: it has a bunch of methods. One of them is the IsValid() method, which is used to validate the property the attribute is applied to. How is this validation performed? I suppose the IsValid() method is called against the property, but I don't find documentation on how to call attribute methods.
Note: I have a Java background. In Java, annotations are intended as metadata and are declared as #intefaces, thus they don't have methods.
In almost all cases, the answer is simply: manually but by code that isn't yours. Some piece of code in some framework that you're using is intentionally checking for those attributes, and then if they exist: materializing them (preferably also with some kind of caching), and invoking the method.
Attributes don't do anything by themselves, but they are still types and can be materialized via the reflection APIs. If you want to write code to do this:
using System;
[SomeAttribute("boop")]
static class P
{
static void Main()
{
var obj = (SomeAttribute)Attribute.GetCustomAttribute(
typeof(P), typeof(SomeAttribute));
// note the attribute doesn't know the context
// so we need to pass that *in*; an attribute
// doesn't know what it has been attached to
obj?.DoSomething(typeof(P));
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Enum)]
class SomeAttribute : Attribute
{
public string Name { get; }
public SomeAttribute(string name)
=> Name = name;
public void DoSomething(Type type)
=> Console.WriteLine($"hey {type.Name} - {Name}");
}
Basically an attribute does nothing in itself, it has to be analysed by some kind of framework. What this framework actually does is completely up to the attributes creator. So the framework may just check if an attribute is present, however it can of course also call its members.
So imagine you have this code:
[MyAttribute]
class MyClass
{
}
class MyAttribute : Attribute
{
public void DoSomething();
}
Now you have some code that checks if the attribuite is present and if so calls DoSomething:
// get types with the attribute
var typesAndAttributes= myAssembly.GetTypes().Select(x => new
{
Type = x,
Attribute = Attribute.GetCustomAttribute(x, typeof(MyAttribute))
});
// now call DoSomething for every attribute
forerach(var e in typesAndAttributes)
{
e.Attribute?.DoSomething();
}
In your example of MaxLengthAttribute this means the following. If you´d decorate your member like this:
MaxLengthAttribute(2)
public int[] MyArr = new int[3];
and execute the code the framework calls IsValid for MyArr and will probably (not sure about it, didn´t inspect the sourcecode) return false, as the value contains 3 elements although only two are considered valid.
As an example, have a look at the attribute MaxLengthAttribute: it has a bunch of methods. One of them is the IsValid() method, which is used to validate the property the attribute is applied to. How is this validation performed? I suppose the IsValid() method is called against the property, but I don't find documentation on how to call attribute methods.
Here's a very simple example:
// Start off with an object we're going to validate
public class Foo
{
[MaxLength(5)]
public string Bar { get; set; }
}
var objectToValidate = new Foo() { Bar = "123456" };
// Use reflection to get a list of properties on the object
var properties = objectToValidate.GetType().GetProperties();
foreach (var property in properties)
{
// For each property, get the attributes defined on that property
// which derive from the ValidationAttribute base class
var attributes = property.GetCustomAttributes<ValidationAttribute>();
var propertyValue = property.GetValue(objectToValidate);
foreach (var attribute in attributes)
{
// For each attribute, call its IsValid method, passing in the value
// of the property
bool isValid = attribute.IsValid(propertyValue);
if (!isValid)
{
Console.WriteLine("{0} is invalid", property.Name);
}
}
}
This is more or less what Validator.ValidateObject does, except with a lot more caching.
(In the case of the DataAnnotations methods, the TypeDescriptor infrastructure is actually used. This lets you effectively add attributes to classes and their properties without modifying the source of the class directly).
Runnable example

Wrapping a Generic class inside a non Generic class C#

I'm working on a C# console application. My objective is to create an object called GroupEntity, preferably of non generic type.
Inside this GroupEntity object will be a List of 'AttributeFilter' object which contains object of Generic type which hold the attribute name on a user object in Active Directory and the possible values of those user objects. The reason I want the AttributeFilter object to take a generic type is because some attributes on user objects in AD are string, some are int32, some are int64 etc.
Here are my classes (I've cut out the contructorse etc to save space here)
public class AttributeFilter<T> : IEqualityComparer<AttributeFilter<T>>
{
private string _attributeName;
private T _attributeValue;
private List<T> _attributeValues { get; set; }
public AttributeFilter(string attributeName)
{
AttributeName = attributeName;
_attributeValues = new List<T>();
}
public void AddValues(T attributeValue)
{
AttributeValue = attributeValue;
if (!_attributeValues.Contains(AttributeValue))
{
_attributeValues.Add(AttributeValue);
}
}
// Ive cut out the getter setter etc that is not relevant
}
Here is the GroupEntity class. Notice I have a
List<AttributeFilter<T>>
field. Problem is I dont know what that T will be until I run program.cs
public class GroupEntity<T>
{
private string _groupName;
// because I want to a have a List<AttributeFilter<T>>, but I dont really want this here. because of program.cs when I initialise a new GroupEntity<> I have to tell it what type. I wont know. The type could be int32, string, long or whatever.
private List<AttributeFilter<T>> _filters;
public void AddFilters(AttributeFilter<T> attributeFilter)
{
if (!_filters.Contains(attributeFilter, attributeFilter))
{
_filters.Add(attributeFilter);
}
}
public GroupEntity()
{
_filters = new List<AttributeFilter<T>>();
}
public GroupEntity(string groupName) : this()
{
_groupName = groupName;
}
}
Now I use program.cs to initialise and test...
class Program
{
static void Main(string[] args)
{
// Create AttributeFilter object for user attribute: EYAccountType
var at1 = new AttributeFilter<string>("EYAccountType");
at1.AddValues("02");
at1.AddValues("03");
at1.AddValues("04");
at1.AddValues("05");
// try adding anothr AtributeFilter with same name.
var at3 = new AttributeFilter<string>("EYAccountType1");
at3.AddValues("06");
at3.AddValues("07");
// Create AttributeFilter object for user attribute: userAccountControl
var at2 = new AttributeFilter<int>("userAccountControl");
at2.AddValues(512);
at2.AddValues(544);
at2.AddValues(546);
at2.AddValues(4096);
// Now create a GroupEntity object
var group1 = new GroupEntity<string>("My_First_AD_Group_Name");
// Try adding the above two AttributeFilter objects we created to the GroupEntity object.
group1.AddFilters(at1);
group1.AddFilters(at3);
// This is the problem. I know why this is happening. because I initialised the var group1 = new GroupEntity<string>. So it wont accept at2 because at2 is taking in int.
//group1.AddFilters(at2);
}
So how can I write my GroupEntity class without a generic parameter so I can hold various types of AttributeFilter<T> inside it. So for example, I can hold AttributeFilter<int> and AttributeFilter<string> and AttributeFilter<long>
I can't seem to figure out this problem.
More or less you can't.
Generic types instantiated with different types has no relationship to each other (i.e. AttributeFilter<long> and AttributeFilter<int> don't get any common base class - they are as differnet as Exception and HttpClient). So there is no way to put instances of such types into single collection with strong typing.
Standard solution - use non-generic base class or interface for your AttributeFilter<T> type. Alternatively - store them as collection of object and lose all type safety, or maybe collection dynamic which at least give you chance to call methods (at cost of reflection).

MethodBase as Hashtable Key

I want to store some backing fields of Properties declared in derived classes in protected Hashtable contained in base class.
The usage of this mechanism in derived classes has to beas simple as possible.
So, can I use MethodBase.GetCurrentMethod() to provide information about calling property (getter - properties are read-only), so it can be recognized as the one and only property that has access to this particular backing field?
EDIT:
Basically, I want to implement pattern:
private SomeClass _someProperty = null;
private SomeClass SomeProperty
{
if (_someProperty == null)
{
_someProperty = new SomeClass();
}
return _someProperty;
}
to look something like this:
private SomeClass SomeProperty
{
return GetProperty(delegate
{
var someProperty = new SomeClass();
return someProperty;
};
}
And in base class
private System.Collections.Hashtable _propertyFields = new System.Collections.Hashtable();
protected T GetProperty<T>(ConstructorDelegate<T> constructorBody)
{
var method = new System.Diagnostics.StackFrame(1).GetMethod();
if (!_propertyFields.ContainsKey(method))
{
var propertyObject = constructorBody.Invoke();
_propertyFields.Add(method, propertyObject);
}
return (T)_propertyFields[method];
}
protected delegate T ConstructorDelegate<T>();
The reason I want to do this is to simplify the usage of properties.
I use private properties to create some objects and use them around the class. But when I store their backing fields in the same class, I have the same access to them as to the properties, so I (means user who would create some derived classes in the future) could accidently use backing field instead of the property, so I wanted to restrict access to backing field, while allow to create object and use it.
I tried to use ObsoleteAttribute on the backing fields like this:
[Obsolete("Don't use this field. Please use corresponding property instead.")]
private SomeClass __someProperty;
private SomeClass _someProperty
{
#pragma warning disable 0618 //Disable Obsolete warning for property usage.
get
{
if (__someProperty== null)
{
__someProperty = new SomeClass();
}
return __someProperty ;
}
#pragma warning restore 0618 //Restore Obsolete warning for rest of the code.
}
But, firstly, I cannot force the user to use this pattern, and secondly, it's to much code to write in derived class, which, as I metioned above, I want to be as simple as possible.
Neither MethodBase nor MemberInfo do not properly overrides Equals and GetHashCode functions, but uses default RuntimeHelpers.GetHashCode and RuntimeHelpers.Equals. So you will only be able to compare same instance, but not same content. In most cases this will be enough as runtime caches that instances to reuse them. But there is no guarantee this will work stable.
As you working with metadata, use something that will identify it uniquely. For example, MemberInfo.MetadataToken. You could write your own comparer and use it inside hashtable:
public class MethodBaseComparer : IEqualityComparer<MethodBase>
{
public bool Equals(MethodBase x, MethodBase y)
{
if (ReferenceEquals(x, y))
return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
return x.MetadataToken.Equals(y.MetadataToken) &&
x.MethodHandle.Equals(y.MethodHandle);
}
public int GetHashCode(MethodBase obj)
{
return (obj.MetadataToken.GetHashCode() * 387) ^ obj.MethodHandle.GetHashCode();
}
}
It not a good idea to restrict access via reflection to some members as other trusted code can use reflection to access other private data outflanking your checks. Consider restrict access via redesigning your classes.
Also take a look at Code Access Security.
Update according to your edit.
You told your properties are read-only. I guess, simply declaring them as readonly is not your option. Looks like you want delayed initialization for properties values. In that case you will not able to declare them as readonly. Right?
Or maybe you can?
Take a look at Lazy<T> class. It's not available in dotnet 2.0, but you can easily implement it or even take any existing implementation (just replace Func<T> with your delegate). Example usage:
public class Foo
{
private readonly Lazy<int> _bar = new Lazy<int>(() => Environment.TickCount, true);
// similar to your constructorBody - ^^^^^^^^^^^^^^^^^^^^^^^^^^^
private int Bar
{
get { return this._bar.Value; }
}
public void DoSomethingWithBar(string title)
{
Console.WriteLine("cur: {0}, foo.bar: {1} <- {2}",
Environment.TickCount,
this.Bar,
title);
}
}
Pros:
It's a lazy initialization as you wish. Let's test it:
public static void Main()
{
var foo = new Foo();
Console.WriteLine("cur: {0}", Environment.TickCount);
Thread.Sleep(300);
foo.DoSomethingWithBar("initialization");
Thread.Sleep(300);
foo.DoSomethingWithBar("later usage");
}
Output will be something like this:
cur: 433294875
cur: 433295171, foo.bar: 433295171 <- initialization
cur: 433295468, foo.bar: 433295171 <- later usage
Note, value initialized on first access and not changed later.
Properties are write-protected by a compiler - _bar field is readonly and you have no access to internal fields of Lazy<T>. So, no any accidental backing field usage. If you try you will get compilation error on type mismatch:
CS0029 Cannot implicitly convert type System.Lazy<SomeClass> to SomeClass
And even if you access it via this._bar.Value, nothing terrible would happen and you will get a correct value as if you access it via this.Bar property.
It is much more simpler, faster and easier to read and maintain.
Thread safety out of the box.
Cons: — (I didn't found)
Few cents about your hashtable-based design:
You (or someone who will maintain your code) can accidentally (or advisedly) access and/or modify either whole hashtable or it's items as it is just a usual private property.
Hashtable is a minor performance hit + getting stacktrace is a huge performance hit. However I don't know if it is critical, depends on how often you access your properties.
It would be hard to read and maintain.
Not thread safe.

How to convert class with generic type to class with object as generic type in C#

Hello I'm using Visual Studio 2005 (because I need compact framework support) and my problem is with generics.
I have created an abstract class called AbstractDAO which is my base
From that I am creating other classes like DocumentDAO,HeaderDAO etc which represent different tables on my database
What I wish to do is retrieve a certain number of the above mentioned DAO classes, but as an AbstractDAO (the abstract class has a number of concrete implementations that I wish to use)
What I tried is
AbstractDAO<object> dao = new DocumentDAO();
AbstractDAO<object> dao = (AbstractDAO<object>)new DocumentDAO();
AbstractDAO<T> dao = new DocumentDAO();
I need the above because I have created a function that transfers data from one table to another similar table in a different database, so it would (if it worked) go something like this
AbstractDAO<object> dao_local = new DocumentDAO(local_database);
AbstractDAO<object> dao_remote = new DocumentDAO(remote_database);
do_transfer(dao_local,dao_remote)
void do_transfer(AbstractDAO<object> from, AbstractDAO<object> to) {
List<object> items = from.get_all();
to.insert(items);
}
Is there any way to do the above?
That will only work if your class hierachy is like this:
class DocumentDAO : AbstractDAO<object> {
//...
}
By your comment it seems like you have a type hierarchy like this:
class DocumentDAO : AbstractDAO<SomeType> {
public override SomeType Foo() {
//...
return someValue;
}
//...
}
class AbstractDAO<T> {
public abstract T Foo();
//...
}
You probably want to refactor AbstractDAO to implement a non generic interface like IAbstractDAO:
class IAbstractDAO {
object Foo();
//...
}
class AbstractDAO<T> {
public object Foo() {
return Foo();
}
public abstract T Foo();
//...
}
Any implementation of AbstractDAO<T> is compiled to a separate object type where T is replaced with the type. See "Is generics runtime or compile time polymorphism?" for more information on how this happens. In short, don't let the <T> fool you.
This means that you can't assign DocumentDAO to AbstractDAO<object> any more than you can assign String to it. Also a generic type is not the same as inheriting, which seems to be what you are trying to achieve.
In either case there are two standard solutions, as already mentioned.
The first is to operate on interfaces. You create an interface for the common properties and have AbstractDAO<T> or any other inherit from this. Then most of the time you simply operate on interfaces. Exactly how you organize it is up to you.
The second is to perform a shallow copy of the object. This means copying values and references from one object to the other. For this you usually use an object mapper like AutoMapper. This tutorial should get you started..
You can try to use Automapper to transfer your objects like this:
void do_transfer(AbstractDAO<FirstType> from, AbstractDAO<SecondType> to)
{
Mapper.Initialize(cfg=>cfg.CreateMap<FirstType, SecondType>);
List<FirstType> fromItems = from.get_all();
List<SecondType> itemsToInsert =
Mapper.Map<List<FirstType>, List<SecondType>>(fromItems);
to.insert(itemsToInsert);
}
By default automapper will map fields with same names. You can create configurations for complex type mapping.
So I finally found the answer to what I was trying to do, instead of assigning abstractDAO to something I created a factory that would retrieve the required AbstractDAO according to what type the generic was, and used this function
private bool transfer<T>(){
AbstractDAO<T> local = DAOFactory.get<T>(local_database);
AbstractDAO<T> remote = DAOFactory.get<T>(remote_database);
List<T> items = local.get_all();
foreach (T item in items) {
remote.insert(item);
}
}
That way I can call this function like this:
transfer< Document >();
transfer< Header >();
etc. and do a full transfer
edit: just for completeness' shake this is the factory I created
public static AbstractDAO<T> get<T>(Database database) {
Type t = typeof(T);
if (t == typeof(Document)) {
return new DocumentDAO(database) as AbstractDAO<T>;
} else if (t == typeof(Header)) {
return new HeaderDAO(database) as AbstractDAO<T>;
} etc.
}

Dynamic Linq Library Help

I have the following class:
public class Item
{
public Dictionary<string, string> Data
{
get;
set;
}
}
and a list of it:
List<Item> items;
I need to filter and order this list dynamically using SQL-Like strings. The catch is, that I need to order it by the Data dictionary.
For example: Order By Data["lastname"] or Where Data["Name"].StartsWith("a"). I thought to use the dynamic linq library, but is there any way that my clients can write without the Data[]? For example:
Name.StartsWith("abc")
instead of
Data["Name"].StartsWith("abc")
?
You could add a property like this:
public class Item
{
public Dictionary<string, string> Data
{ get; set; }
public string Name { get { return Data["lastname"]; } }
}
//Call by: i.Name.StartsWith("abc");
Or an extension method:
public static class ItemExtensions
{
public static string Name(this Item item)
{
return item.Data["lastname"];
}
}
//Call by: i.Name().StartsWith("abc");
Or if it's a very commonly used method, you could add something like a .NameStartsWith():
public static string NameStartsWith(this Item item, stirng start)
{
return item.Data["lastname"].StartsWith(start);
}
//Call by: i.NameStartsWith("abc");
This doesn't have anything to do with the Linq Dynamic Query unit. That unit is for when you have actual fields/properties and the names of them will be given to you at runtime. In other words, you have a class like this:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
And you want to be able to write a query like this:
var sortedPeople = people.OrderBy("FirstName");
You are trying to do the exact opposite of this - you have a class that does not have any actual properties, just an attribute dictionary, and you want compile-time safety. You can't have it; there's no way to guarantee that an item will be in the dictionary, especially when the dictionary is public and anyone can add/remove directly from it!
If there's some reason that you must use that specific class design, then you could conceivably write some wrappers as Nick has presented, but I wouldn't even bother - they're not actually providing any encapsulation because the Data dictionary is still wide open to the whole world. Instead, I would just provide a single safe getter method or indexer property and create a few constants (or an enum) with the names of properties you expect to be in there.
public class Item
{
public Dictionary<string, string> Data { get; set; }
public string GetValue(string key)
{
if (Data == null)
return null;
string result;
Data.TryGetValue(key, out result);
return result;
}
}
public class ItemKeys
{
public const string Name = "Name";
public const string Foo = "Foo";
}
And so on. Really the ItemKeys isn't that important, the safe GetValue method is what's important, because otherwise you run the risk of a NullReferenceException if Data hasn't been assigned, or a KeyNotFoundException if even one Item instance doesn't have that property. Using the GetValue method here will succeed no matter what:
var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));
If you find you're writing a lot of repetitive code for the same attributes, then start worrying about adding shortcut properties or extension methods to the class.
I assume that you don't know the names of the properties at compile-time (in which case, you could simply define properties and wouldn't have this problem). I have two suggestions that you could try, but I didn't implement any of them myself, so I can't guarantee that it will work.
If you can use .NET 4.0, you could inherit from DynamicObject and implement TryGetMember method (which is called when you use o.Foo on an object that is declared as dynamic). Assuming that Dynamic LINQ works with DLR, it should automatically invoke this method for objects that inherit from DynamicObject. Inside the TryGetMember method, you would get a name of the accessed property, so you could perform a dictionary lookup. (However, this solution would work only if Dynamic LINQ integrates well with DLR).
In any case, you could do some basic parsing of the string entered by the user and replace for example Name with Data["Name"]. This would definitely work, but it may be a bit difficult (because you should probably at least check that you're doing the replace in correct context - e.g. not inside a string constant).
Regarding extension methods - I'm not sure if Dynamic LINQ handles extension methods (but, I don't think so, because that would require searching all referenced assemblies)

Categories

Resources