Static method in generic class causes CA1000 warning [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
Improve this question
I'm working on a library to manage objects (Animals in my sample code). I have a base class named Animal and a generic class named SpecificAnimal. I also have Dog, Cat etc. which are implemented with the SpecificAnimal class.
If a user wants to create a dog, it is as simple as:
var myDog = new Dog()
{
Name = "Rover",
Age = 3
};
myDog.Add();
The class hierarchy looks like this:
Animal Class
public abstract class Animal
{
public static Animal GetByName(string animalName)
{
// Code that can read any kind of animal from a database
// and create an instance of the correct type
throw new NotImplementedException();
}
public static Animal GetById(int animalId)
{
// Code that can read any kind of animal from a database
// and create an instance of the correct type
throw new NotImplementedException();
}
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public void Add()
{
// Add this Animal to the database
}
public void Update()
{
// Update this animal
}
}
Generic SpecificAnimal class
public abstract class SpecificAnimal<T> : Animal where T : SpecificAnimal<T>
{
public static string Genus { get; protected set; } = String.Empty;
public new static T GetByName(string animalName)
{
// Code that can read an object of type T from a database
return (T)Animal.GetByName(animalName);
}
public new static T GetId(int animalId)
{
// Code that can read an object of type T from a database
return (T)Animal.GetById(animalId);
}
}
Dog class
public class Dog : SpecificAnimal<Dog>
{
public Dog()
{
Genus = "Canis";
}
// Dog specific properties and methods
}
This code is working and (in my opinion) is easy for the consumer of the library to use.
My problem is that the static properties and methods in the SpecificAnimal class generate the warning:
CA1000: Do not declare static members on generic types
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1000
The documentation for CA1000 says "Do not suppress..." but, it doesn't suggest a better solution. If I shouldn't have static members in a generic class, what should I be doing?
The documentation says that static methods in a generic type are bad because of this awkward syntax:
var myDog = SpecificAnimal<Dog>.GetByName("Rover");
I agree but, my users should never do that. Although, I don't know of a way to prevent it.
How can I add static members to a generic class without generating CA1000? How can I protect the SpecificAnimal class so that the user only has access to Dog and Animal?

The warning exists because there's risk that the behavior might be different than the programmer expects. However, sometimes it's a useful pattern. I ran into this a few weeks ago when building a library.
Let's look at a more simplified example:
void Main()
{
Baz<string>.Counter++;
Baz<int>.Counter++;
Console.WriteLine(Baz<object>.Counter);
}
public abstract class Foo
{
public static int Counter { get; set; }
}
public class Baz<T> : Foo
{
}
What is output? It's easy to think the output would be 0 because Baz<object> is a different closed generic type than Baz<string> or Baz<int>. In fact, the output is 2 because both post increment operations affect the same static variable.

The property can be rewritten as in the example.
public abstract class SpecificAnimal<T> : Animal where T : SpecificAnimal<T>
{
public virtual string Genus { get; } = String.Empty;
}
public class Dog : SpecificAnimal<Dog>
{
public override string Genus { get; } = "Canis";
}
Note that implementing the static new method does not work in the same way as inheritance.

Related

Unable to cast covariant generic interfaces [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have two interfaces:
public interface ISnack { }
public interface IWrapper<TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
And a two classes:
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
CheeseCake c;
public void Wrap(CheeseCake snack)
{
c = snack;
}
}
public class CheeseCake : ISnack { }
I want to execute
IWrapper<ISnack> wrappedSnack = (IWrapper<ISnack>)(new CheeseCakeContainer());
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
But this throws an invalid cast exception
System.InvalidCastException: 'Unable to cast object of type
'CheeseCakeContainer' to type 'IWrapper`1[ISnack]'.'
What should I change to make the cast work? I am using C#9 and .NET5
The crux of your issue is that you are trying to create a container that is covariant, or where you are assigning a more derived type to a more generic type (CheeseCake to
ISnack) while simultaneously attempting to call an interface method that should be contravariant, or implementing a more derived type (CheeseCake). This type of bi-directional variance is illegal in C#.
As a result, you have essentially two options. You can abandon the covariance during your container creation which allows you to maintain contravariance in your implementation, or you can use covariance during your container creation, but you will be forced to cast to your target type in your implementation in order to satisfy the interface.
The former with a contravariant IWrapper<in TSnack> definition:
CheeseCakeContainer wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<in TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(CheeseCake snack)
{
snack.Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}
The latter:
IWrapper<ISnack> wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<out TSnack> where TSnack : ISnack
{
void Wrap(ISnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(ISnack snack)
{
((CheeseCake)snack).Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}

Define a function as taking any object with given properties [duplicate]

This question already has answers here:
Generating Interfaces from entity framework database first auto-generated code
(3 answers)
Closed 3 years ago.
Consider a function LengthOfName; it takes in an object which has a name property, and returns the length of it's name:
class Dog {
public string Name;
}
class Human {
public string Name;
}
class MainClass {
public static int LengthOfNameDog (Dog dog) {
return dog.Name.Length;
}
public static int LengthOfNameHuman (Human human) {
return human.Name.Length;
}
public static void Main (string[] args) {
var Fido = new Dog { Name = "Fido" };
var Alex = new Human { Name = "Alex" };
Console.WriteLine (LengthOfNameDog(Fido));
Console.WriteLine (LengthOfNameHuman(Alex));
}
}
This isn't great, as we have to repeat ourselves. I understand that there is already a standard way around this, namely to have Dog and Human inherit from a single class, for instance:
class ThingWithName {
public string Name;
}
class Dog : ThingWithName {}
Which is fine. The problem I'm having is that I'm using class definitions which are auto-generated from Entity Framework, so I don't think I'd want to mess with their class to say they inherit from some master class.
What I'd like to be able to do is to implement a function which takes in an instance of any object which has given properties, in the example above, for instance, any object which has the Name property.
Is this possible in c#?
Since Entity Framework generates partial entity classes, you can define an interface with a Name property and create another partial class for each entity type that implements this interface:
public interface IHasName
{
string Name { get; }
}
public partial class MyEntity : IHasName {}
public partial class MyOtherEntity : IHasName {}
public static int LengthOfNameHuman (IHasName entity) {
return entity.Name.Length;
}
If the entities don't share a common base class or interface, you'll have to use reflection to get the Name property.

C# Passing current generic class instance to other class

lately I started to learn generics. I run into trouble with storing references to generic classes instances. As you can see, my class ListHandler can store references to specific type of BaseClass. I would love to register BaseClass instances by themselves, which is why I wanted to guarantee that they will use BaseParamClass by adding 'where'. Anyway - it does not compile.'This', does not know that T is actually BaseClassParam even with 'where' keyword in class. I don't know what is wrong here and I couldn't find answer anywhere. I would be grateful for tips/guides/solutions.
public class ListHandler
{
private List<BaseClass<BaseParamClass>> list;
public ListHandler()
{
list = new List<BaseClass<BaseParamClass>>();
}
public void Register(BaseClass<BaseParamClass> param)
{
list.Add(param);
}
}
public class BaseClass<T> where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this); //throws error
}
}
Why don't you make ListHandler generic as well?
public class ListHandler<T>
{
private List<BaseClass<T>> list;
public ListHandler()
{
list = new List<BaseClass<T>>();
}
public void Register(BaseClass<T> param)
{
list.Add(param);
}
}
public class BaseClass<T>
{
private ListHandler<T> listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler<T> listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Also, it seems strange to me to have BaseClass<T> contain a reference to a class that has a reference to BaseClass<T> itself.
I have another option for you.
Let's split the BaseClass<T> class into two with a non-generic base, like so:
public class BaseClass
{
protected ListHandler listHandler;
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
}
}
public class BaseClass<T> : BaseClass where T : BaseParamClass
{
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
: base(listHandler)
{
listHandler.Register(this); // Compiles nicely! Yay!
}
}
Now, the list inside ListHandler can be defined as private List<BaseClass> list;. That means there is no problem adding any BaseClass item to the list. We also can then define two methods for registering and fetching generic versions of the BaseClass<T> from the ListHandler. It would look like this:
public class ListHandler
{
private List<BaseClass> list;
public ListHandler()
{
list = new List<BaseClass>();
}
public void Register<T>(BaseClass<T> param) where T : BaseParamClass
{
list.Add(param);
}
public BaseClass<T> Fetch<T>() where T : BaseParamClass
{
return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
}
}
So, given a class public class FooParam : BaseParamClass { } I can write this code:
ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();
Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));
The result from this code is True is written to the console - which means I can successfully fetch the instance of BaseClass<FooParam> from the ListHandler.
Why your code doesn't compile
In order to fully understand why your code doesn't compile, you'll have to dive into covariance and contravariance, which is a big topic and hard to explain in an SO answer. It can be especially confusing if you've gotten to a point where inheritance polymorphism is second nature to you; the rules are just different enough to be make your head hurt.
Here is what is confusing--
You're used to doing this:
object a = new String(...);
But generics don't let you do this!
List<object> c = new List<string>(); //Compiler error
That's because those two Lists are not related the same way that object and string are related. One does not inherit from the other. Rather, they are different variants of a generic type definition. In the generic world, you can't assign one to the other. The same is true of this:
void Foo<T>() where T: BaseParamClass
{
BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}
In this example, T could be BaseParamClass or one of its derived types. They are not the same type. So to remain type-safe, the compiler has to disallow this assignment, and your Register call, which has the same type mismatch.
Standard ways around this
You need a covariant interface. These allow assignment from derived to base. So for example, while this is still illegal:
List<object> a = new List<string>(); //Compiler error
This is totally fine:
IEnumerable<object> e = new List<string>(); //Is OK
Because IEnumerable was declared to be covariant, like this:
interface IEnumerable<out T>
Which means it is can be assigned in this way. It works because using out also adds a compiler constraint to the interface: it can be used to retrieve stuff...
interface IEnumerable<out T>
{
T Item[int index];
}
...but it cannot accept anything:
interface IEnumerable<out T>
{
Add(T item); //Compiler error
}
These constraints are what allow generics to provide early-bound type safety while still allowing certain forms of (non-inheritance) polymorphism.
What I'd suggest
Based on your comment, it sounds like you just need a container (a stack, apparently) that can hold references to these BaseClass<T> instances. If you are following separation of concerns, the stack doesn't need to actually do anything with the T, other than store it and retrieve it, and to allow it to register itself.
Since that is a separate concern, make a separate interface.
And in the interest of keeping things simple, maybe avoid using generics completely for this bit.
One way to do it--
Create an interface that allows access to everything the stack needs to know about an item it is containing. For example, if the stack contains popups of various kinds, you may want to expose the popup's title.
interface IStackable
{
string Title { get; set; }
}
Now use it like this:
public class ListHandler
{
private readonly Dictionary<string, IStackable> list;
public ListHandler()
{
list = new Dictionary<string, IStackable>();
}
public void Register(IStackable item)
{
list.Add(item.Title, item);
}
}
public class BaseClass<T> : IStackable where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
public string Title { get; set; }
}
Unless there is some other requirement, you shouldn't need to make it any more complicated than that.
All you really need to do is add an interface. This works:
public class BaseParamClass
{
}
public class ListHandler
{
private List<IBase<BaseParamClass>> list;
public ListHandler()
{
list = new List<IBase<BaseParamClass>>();
}
public void Register(IBase<BaseParamClass> param)
{
list.Add(param);
}
}
public interface IBase<T> where T : BaseParamClass
{
T Param {get; }
}
public class BaseClass : IBase<BaseParamClass>
{
private ListHandler listHandler;
public BaseParamClass Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Working code on DotNetFiddle

instantiate a generic class using reflection [duplicate]

This question already has answers here:
How to dynamically create generic C# object using reflection? [duplicate]
(5 answers)
Closed 9 years ago.
[NOTE: I don't believe this question is a duplicate of the one linked above, as I explain in the UPDATE below.]
Is there any way to define/instantiate a generic class using reflection?
So I have a bunch of classes, each of which owns an instance of a generic class that shares the type of its owner:
public class GenericClass<T>
{
T Owner { get; set; }
public GenericClass(T owner) { Owner = owner; }
}
public class MyClass
{
private GenericClass<MyClass> myGenericObject;
public MyClass() { myGenericObject = new GenericClass<MyClass>(this); }
}
This works, but of course I have to explicitly specify "MyClass" as the argument in the GenericClass definition. I'd like to be able to do something like this:
private GenericClass<typeof(this)> myGenericObject; // Error: invalid token
Is there anyway to dynamically specify the type of the generic object at compile time, based on the containing class?
UPDATE: After reading the answers from these questions, I learned that I could instantiate a local variable like so:
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(this.GetType()));
but, of course, the this keyword is only available inside a method (so, for example, I could put this line of code in the constructor of MyClass). But I cannot use this approach to define an instance variable (i.e., myGenericObject, in the code above). Is there any way to specify a generic instance variable dynamically?
Regarding your update, you can pass any Type to MakeGenericType. For example, the following also works:
var myObject = new MyClass();
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(typeof(MyClass)), myObject);
Console.WriteLine(myGenericObject.GetType());
Outputs:
ConsoleApplication1.GenericClass`1[ConsoleApplication1.MyClass]
myObject.GetType() also does the same thing:
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(myObject.GetType()), myObject);
Not sure if that is what are you looking for but can try with inheritance:
public class GenericClass<T>
{
T Owner { get; set; }
public GenericClass(T owner) { Owner = owner; }
}
public abstract class MyClassBase<T> where T : MyClassBase<T>
{
protected GenericClass<T> MyGenericObject { get; private set; }
protected MyClassBase() { MyGenericObject = new GenericClass<T>((T)this); }
}
public class MyClass1 : MyClassBase<MyClass1>
{
public MyClass1() { }
}
public class MyClass2 : MyClassBase<MyClass2>
{
public MyClass2() { }
}
There is static built in construct for that:
Activator.CreateInstance()
Look at the overloads.
UPDATE
public Type FakeType { get; private set; }
public T CreateInstance<T>() where T : SomeEntityBase
{
return (T) Activator.CreateInstance(FakeType);
}

Can't define static abstract string property

I've run into an interesting problem and am looking for some suggestions on how best to handle this...
I have an abstract class that contains a static method that accepts a static string that I would like to define as an abstract property. Problem is that C# doesn't doesn't support the following (see the ConfigurationSectionName and Current properties):
public abstract class ProviderConfiguration : ConfigurationSection
{
private const string _defaultProviderPropertyName = "defaultProvider";
private const string _providersPropertyName = "providers";
protected static string ConfigurationSectionName { get; }
public static Configuration Current
{
get { return Configuration)ConfigurationManager.GetSection(ConfigurationSectionName); }
}
}
I suppose one way to handle this would be to make ConfigurationSectionName NOT abstract and then create a new definition of ConfigurationSectionName in the derived classes, but that feels pretty hackish. Any suggestions would be most welcome.
Gratias!!!
Static members do not have polymorphism, so they can't be abstract. :(
If that's what you need, consider making a Singleton object, and reading the property off that object.
Just use new to override a static method in a derived class. Nothing that makes new a bad thing to do for virtual methods and properties applies since the type name must be supplied:
public class BaseClass
{
public static int Max { get { return 0; } }
}
public class InteriorClass : BaseClass
{
}
public class DerivedClass : InteriorClass
{
public new static int Max { get { return BaseClass.Max + 1; } }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("BaseClass.Max = {0}", BaseClass.Max);
Console.WriteLine("InteriorClass.Max = {0}", InteriorClass.Max);
Console.WriteLine("DerivedClass.Max = {0}", DerivedClass.Max);
Console.ReadKey();
}
}
Ok, this is not exactly to create an static abstract property, but you can achieve the desired effect.
You can get this by using generics:
public abstract class MyAbstractClass<T>
{
public static string MyAbstractString{ get; set; }
public static string GetMyAbstracString()
{
return "Who are you? " + MyAbstractString;
}
}
public class MyDerivedClass : MyAbstractClass<MyDerivedClass>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClass>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClass>.MyAbstractString = value;
}
}
}
public class MyDerivedClassTwo : MyAbstractClass<MyDerivedClassTwo>
{
public static new string MyAbstractString
{
get
{
return MyAbstractClass<MyDerivedClassTwo>.MyAbstractString;
}
set
{
MyAbstractClass<MyDerivedClassTwo>.MyAbstractString = value;
}
}
}
public class Test
{
public void Test()
{
MyDerivedClass.MyAbstractString = "I am MyDerivedClass";
MyDerivedClassTwo.MyAbstractString = "I am MyDerivedClassTwo";
Debug.Print(MyDerivedClass.GetMyAbstracString());
Debug.Print(MyDerivedClassTwo.GetMyAbstracString());
}
}
So, calling the test class you will get:
"Who are you? I am MyDerivedClass"
"Who are you? I am MyDerivedClassTwo"
So, you have an static method in an abstract class but the abstract value is different for each derived class, nice :D
Ok, so, what's going here? The trick is the generic tag, the compiler is generating a different abstract class for each derived type.
As I said it's not an abstract property, but you get all benefits of abstract static properties, which are programming static functions on your abstract class but using different static parameters per type.
Elsewhere on this page, #Gusman proposes the nice solution distilled here:
abstract class AbstractBase { };
abstract class AbstractBase<T> : AbstractBase
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived1>.AbstractStaticProp = value;
}
};
class Derived2 : AbstractBase<Derived2>
{
public static new String AbstractStaticProp
{
get => AbstractBase<Derived2>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
};
Moving the static property from a non-generic to generic class means there is no longer necessarily a single global instance. There will be a unique AbstractStaticProp for each distinct type T, so the idea is that specifying the type of the derived class(es) themselves for T guarantees each of them generates a unique static for themselves. There are a few hazards to note with this, however.
If for some reason it is not acceptable for AbstractBaseClass to be generic, then you've only moved the problem elsewhere (albeit more clearly distilled), because you still have to figure out how to statically call from AbstractBase to AbstractBase<T>.
Mainly, there is nothing to enforce or require that any/every given derived class actually does "implement" the (psudo-) "overridden" static property;
Related to this, since there is no compiler (polymorphic) unification going on here, correct signatures (method name, parameter arity, typing, etc.) for the "overridden" methods aren't enforced either.
Although the generic parameter is intended to be "TSelf" of a derived class, in reality T is unconstrained and essentially arbitrary. This opportunizes two new classes of bug: if base class specification Y : AbstractBase<...> mistakenly references a different AbstractBase‑der­ived class X, the values of the "abstract static property" for X and Y will be incorrectly conflated -- and/or -- any usage call-site AbstractBase<T>.AbstractStaticProp with a mistaken type argument (such as DateTime) will spontaneously--and silently--demand a fresh new "instance" of the static property.
The last bullet point can be somewhat mitigated by adding a constraint on the generic base:
/// v---- constraint added
abstract class AbstractBase<TSelf> where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
This eliminates the possibility of class Derived2 : AbstractBase<DateTime> { /*...*/ }, but not the error class Derived2 : AbstractBase<Derived1> { /*...*/ }. This is due to a recurring conundrum that foils all attempts at constraining a generic type to some exact branch of the type-inheritance hierarchy:
The "TSelf problem"
Generic constraints are always at the mercy of the type arguments that are supplied, which seems to entail that it's impossible to construct a generic constraint that guarantees that some particular TArg within its scope refers to a type that is derived from itself, that is, the immediate type being defined.
The error in this case is an example of this; while the constraint on AbstractBase<TSelf> rules out incompatible disjoint types, it can't rule out the unintended usage Derived2 : AbstractBase​<Derived1>. As far as AbstractBase is concerned, the supplied type argument Derived1 satisfies its constraint just fine, regardless of which of its subtypes is deriving itself (im-)properly. I've tried everything, for years, to solve TSelf; if anyone knows a trick I've missed, please let me know!
Anyway, there are still a couple other points to mention. For example, unless you can immediately spot the problem in the following code, you'll have to agree that it's a bit dangerous:
public static new String AbstractStaticProp
{
get => AbstractBase<Derived1>.AbstractStaticProp;
set => AbstractBase<Derived2>.AbstractStaticProp = value;
}
Ideally, you want to get the compiler to do what it's meant to, namely, understand that all AbstractStaticProp property instances are related and thus somehow enforce their unification. Since that's not possible for static methods, the only remaining option is to eliminate the extra versions, effectively reducing the problem to the unification of just one, a vacuous operation, obviously.
It turns out that the original code is being too elaborate; the generic-base class approach wants to collapse on the simpler solution all by itself without having to explicitly request it, such as those new-marked properties seem to be doing with the qualification in AbstractBase<Derived1>.​AbstractStaticProp".
You can already refer to each respective independent copy of the static property by qualifying with the derived class name instead (in fact, #Gusman's test harness shows this), so the end result is that the property declarations in the derived class aren't necessary at all. Without further ado, here is the complete simplified version:
abstract class AbstractBase { };
abstract class AbstractBase<TSelf> : AbstractBase
where TSelf : AbstractBase<TSelf>
{
public static String AbstractStaticProp { get; set; }
};
class Derived1 : AbstractBase<Derived1> { };
class Derived2 : AbstractBase<Derived2> { };
This works identically to the code at the top. The test harness gives the same results as before.
static void Test()
{
Derived1.AbstractStaticProp = "I am Derived1";
Derived2.AbstractStaticProp = "I am Derived2";
Debug.Print(Derived1.AbstractStaticProp); // --> I am Derived1
Debug.Print(Derived2.AbstractStaticProp); // --> I am Derived2
}
What you're trying to do is impossible, as others have mentioned.
I'd try something like this
public abstract class ProviderConfiguration : ConfigurationSection
{
public string ConfigurationSectionName { get; set; }
public static ProviderConfiguration Provider { get; set; }
public static Configuration Current
{
get { return (Configuration)ConfigurationManager.GetSection(Provider.ConfigurationSectionName); }
}
}
Then in practice:
public void DoStuff()
{
var provider = new DerivedProviderConfiguration();
ProviderConfiguration.Provider = provider;
}

Categories