Reputation: 11
I need a way to force a subclass of one of my classes to declare a specific static method. For example a type safe FromFile or FromStream function. Similar to the concept of abstract methods for a non static context.
I know I could use constructs like this:
return (T)typeof(T).GetMethod("FromFile").Invoke(null, new[] { someArgs });
But this would only throw an exception during runtime if the method is not defined. But what I want is to make the code not compile if it isn't there.
I also know that I could get all those loader methods at startup and store them in a static Type-Loader map, but still it would only throw an exception during application startup.
For this example I am using a texture loader that should be able to load different types of textures as long as they inherit the same base class. (OpenGL Texture Wrappers, DX Texture Wrappers, Video Textures, etc)
public abstract class DataContainer<T>
{
public abstract T Load(object someArgs);
[...]
}
public class TextureContainer<T> : DataContainer<T> where T : Texture<T>
{
public override T Load(object someArgs)
{
if (/*is currently loaded*/)
return GetLoadedFile(someArgs);
else
return T.FromFile(someArgs);
}
[...]
}
A base class for texture would look something like this:
public abstract class Texture<T> where T : Texture<T>
{
//works fine, forces derived class to declare a type safe Clone method
public abstract T Clone();
//sadly for static methods I can't do the same
//so I need another way here
public static /*abstract*/ T FromFile(object someArgs);
}
Then a concrete implementation of texture would look like this:
public class DirectXTexture : Texture<DirectXTexture>
{
//works fine
public override DirectXTexture Clone()
{
throw new System.NotImplementedException();
}
//another way needed
public static /*override*/ DirectXTexture FromFile()
{
throw new System.NotImplementedException();
}
}
Having this setup you could simply get a texture by using the following code with the base DataContainer loading and unloading the texture whenever necessary or performing the loading task in a background thread.
static class Program
{
static void Main(string[] args)
{
var container = new TextureContainer<DirectXTexture>();
var tex = container.Load("some file");
}
}
Just to clarify: I already have a fully working DataContainer construct that can load resources in main or background threads and monitor instances that reference my resources so I can unload them if nobody needs them anymore. The only thing I need is the functionality of creating a container for an ABSTRACT type with their corresponding load methods so I do not have to create a seperate sub class for DXTextureContainer, GLTextureContainer, VideoTextureContainer etc.
I hope you guys can help me here. Thanks in advance!
Upvotes: 1
Views: 47
Reputation: 14856
Up to C# 8.0 there's no way to enforce that.
Starting with Visual Studio 2017 you can write a Roslyn analyzer to flag that (and make it a compilation error, if you want it) and even offer a fix.
Upvotes: 1