Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i associate a static string with an object type C#

Tags:

c#

.net

generics

I have a method that queries a rest API where I do a mapping from JSON to an object. Since the query string and object type I pass to this method always have to match I wanted to include the query string as a static string.

public class Root
{
    public static string Query;
}

public class RootObject : Root, IRootObject
{
    public D d { get; set; }
    public static new string Query = "AccountSet";
}

public interface IRootObject
{
    D d  { get; }
}

public class RestClass
{
     public void Connect<T>() where T : Root, IRootObject
     {    
        T.Query  <-- fails (not actual code. Just to show my problem)
     }  
}
like image 528
SondreBBakken Avatar asked Mar 05 '15 11:03

SondreBBakken


2 Answers

You could use a custom attribute for this:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class QueryAttribute : Attribute
{
    public string QueryString { get; private set; }

    public QueryAttribute(string queryString)
    {
        QueryString = queryString;
    }

    public static string GetQueryStringForType(Type type)
    {
        var queryAttr = type.GetCustomAttributes(typeof(QueryAttribute), false)
                            .FirstOrDefault() as QueryAttribute;

        return queryAttr != null ? queryAttr.QueryString : null;
    }
}

Use it on your classes:

[Query("AccountSet")]
public class RootObject : Root, IRootObject
{
    public D d { get; set; }
}

And retrieve the value like this:

public void Connect<T>() where T : Root, IRootObject
{
    var query = QueryAttribute.GetQueryStringForType(typeof(T));
}
like image 120
Lucas Trzesniewski Avatar answered Nov 15 '22 12:11

Lucas Trzesniewski


As opposed to languages such as Delphi, C# and the .NET CLI in general do not support the concept of static polymorphism.

Therefore, you will require some other way to attach the type-specific information to your types, two of which I suggest here:

  1. You can use a custom attribute to mark your class. That attribute can be retrieved from typeof(T) with reflection methods such as GetCustomAttributes. Once you have defined your attribute class, these attributes are quite easy to declare for each type that you want to pass to T. The downside is that there is no way to compile-time check whether every class passed to T is adorned by such an attribute.
  2. Alternatively, you can go for an "info object". Create a base class ObjectInfo<T> that serves as a factory for an instance of type T and as a storage for some metainformation on T, for example your Query string. For each type that you want to pass to T, subclass your ObjectInfo<T> where T : Root class (e.g. create a class RootObjectInfo : ObjectInfo<RootObject> that overrides the Query property of ObjectInfo<T> to return the appropriate string). Then, modify Connect<T> so it requires an ObjectInfo<T> as an argument.
like image 43
O. R. Mapper Avatar answered Nov 15 '22 11:11

O. R. Mapper