I have a class hierarchy that represents a JSON based API. There is a generic factory that calls and deserializes the api into classes using .NET 4 (no 3rd party libs). I am trying to avoid having to instantiate the class to retrieve a read-only piece of information that is unique to each class.
I had thought (until I started reading this and this, ...) I would associate a static URL with a base class/interface and then set it in the derived class's constructor. Something like (this example will not work):
abstract class url {
public abstract static string URL; // This is invalid syntax!
}
class b : url {
static b () { URL = "http://www.example.com/api/x/?y=1"; }
}
class c: url {
static c () { URL = "http://www.example.com/api/z"; }
}
// ... so the factory can do something like ...
b result = doJSONRequest<b>(b.URL);
This doesn't work. The static field can't be abstract, nor can it be uniquely set in b and c as the static variable is stored in the class it is defined in (url in this case).
How can I have a read only item associated with a class such that you can access the item (etc.) without having to instantiate the class?
I've implemented a pattern like this to help remind me of constants that I need to setup per derived class that need to be statically accessible:
public abstract class Foo
{
public abstract string Bar { get; }
}
public class Derived : Foo
{
public const string Constant = "value";
public override string Bar
{
get { return Derived.Constant; }
}
}
I've even found that after implementing this pattern that the polymorphic use of the constant to be just as helpful.
I understand you don't want to have to ask a instance but keep the method static. This is impossible, static field is loaded once in a module, and cannot be inherited.
I think the only way is to store a dictionary in a helper class, with the type as a key. Like this
class Helper
{
static Dictionary<Type,string> _urls;
public static string GetUrl(Type ofType)
{
return _urls[ofType];
}
public static void AddUrl(Type ofType, string url)
{
_urls.Add(ofType,url);
}
}
class b
{
static b(){ Helper.AddUrl(typeof(b)," ");}
}
class Program
{
b result= doJSONRequest<b>(Helper.GetUrl(typeof(b));
}
Or you can decorate the desired types with a custom attribute and store the data in that attribute. Like this
class UrlAttribute:Attribute
{
public string Url{get;private set;}
public UrlAttribute(string url){Url=url;}
}
[Url("someurl")]
class b { }
class Program
{
void Main()
{
UrlAttribute attr = (UrlAttribute)Attribute.GetCustomAttribute(typeof(b), typeof(UrlAttribute));
//in dot net 4.5 you can ask the type itself
UrlAttribute attr = (UrlAttribute)typeof(b).GetCustomAttribute(typeof(UrlAttribute));
//now you can write that...
b result = doJSONRequest<b>(attr.Url);
}
//or even you can do that in doJSONRequest itself
public T doJSONRequest<T>()
{
UrlAttribute attr = (UrlAttribute)typeof(T).GetCustomAttribute(typeof(UrlAttribute));
...
//call it: b result=doJSONRequest<b>();
}
}
Of course you can pass on them all by reflection and initialize a dictionary, see this question.
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