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)
}
}
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));
}
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:
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.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.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With