This question already has answers here:
What's a good threadsafe singleton generic template pattern in C#
(23 answers)
Closed 9 years ago.
I am trying to create a generic singleton base class like
public class SingletonBase<T> where T : class, new()
{
private static object lockingObject = new object();
private static T singleTonObject;
protected SingletonBase()
{
}
public static T Instance
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if(singleTonObject == null)
{
lock (lockingObject)
{
if(singleTonObject == null)
{
singleTonObject = new T();
}
}
}
return singleTonObject;
}
}
But I have to make constructor as public in derived one.
public class Test : SingletonBase<Test>
{
public void A()
{
}
private Test()
: base()
{ }
}
Compilation Error:
'Test' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test'
How can I achieve this?
The problem is your generic constraint where T : class, new(). The new() constraint requires a public, parameterless constructor on T. There is no way around this; you need to provide such a constructor in Permission Controller.
I would avoid this kind of recursive generic pattern. Read this this blog post for a detailed explanation of the pattern and reasons not to use it.
As far as I can tell, you don't need to have any sub-classes of SingletonBase<T>. I can't see anything that a subclass of SingletonBase<T> would be able to add to your code. I would simply rewrite it as
public static class Singleton<T> where T : class, new()
{
...
}
You can then use it as
var test = Singleton<Test>.Instance;
If you want to be able to use Test as a singleton, create it as
public class Test
{
public static T Instance
{
get { return Singleton.Instance<Test>; }
}
}
Related
I have the following base class (omitted version):
class BaseClass
{
}
I create the following derived classes:
class DataPreparationClass<T> : BaseClass
{
}
class DataClass<T,U> : DataPreparationClass<T>
{
public virtual void Start<U>(U arg)
{}
}
class DataClassMain : DataClass<InputData,Data>
{
public override void Start(Data argument)
{
base.Start(argument);
}
}
class DataClassAux : DataClass<InputData,AuxData>
{
public override void Start(AuxData argument)
{
base.Start(argument);
}
}
I have a List<BaseClass> containing various derived instances (there are more derived types) and I intend to call their Start method respectively:
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object arg = GetArgsForInstance(instance);
// instance.Start(arg); //can't call this
}
However, as their common base is the BaseClass, I can't call Start without casting to...basicly every possible type as their types are unknown at the processing.
If I use dynamic:
((dynamic)target).Start(new Data("starting")); //target is of type DataClassMain<InputData,Data>
I get an exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best
overloaded method match for
'Client.DataClass<InputData,Data>.Start(Data)' has some invalid
arguments'
So how should I call the unknown method?
So, the most straight forward answer to your question would be to use pattern matching to call the start method.
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object arg = GetArgsForInstance(instance);
switch(instance){
case DataClassMain d : d.Start((Data)arg); break;
case DataClassAux a : a.Start((AuxData)arg);break;
default: throw new Exception();
}
}
But I do get the feeling this is an convoluted and inappropriate inheritance chain, and you should really consider using a factory and/or strategy pattern instead.
It's assumed that GetArgsForInstance allways will return the correct type with respect to the type it receives as an argument, and that the return types (Data, AuxData and so on) share a common base type. So we could do the type resolution directly with a signature of T GetArgsForInstance<T>(BaseClass b). That way you can make sure you get args of the right type before you return it.
Since the Start overrides just pass along the call generic types, so the overrides in DataClassMain and DataClassAux are unnecessary.
If we modify DataClass a bit we can then do it like this:
class DataClass<T,U> : DataPreparationClass<T>
{
public virtual void Start(U arg)
{
//Do somethin with arg
}
public void Call(Func<BaseClass,U> f){
U data = f.Invoke(this);
Start(data);
}
}
and invoke it with
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
switch(instance)
{
case DataClassMain d : d.Call(GetArgsForInstance<Data>); break;
case DataClassAux a : a.Call(GetArgsForInstance<AuxData>);break;
default: throw new Exception();
}
}
The reason this is preferable is that we can let the compiler ensure that we only pass the appropriate types to the different methods, no casting needed.
But again, such a convoluted inheritance chain should almost always be avoided.
I would say, your questions shows multiple flaws in your model:
by definition of your classes, there is no polymorphism inbetween you Start() methods : Start(Data) do not override Start<U>(U)
by definition of your GetArgsForInstance() method, you have lost the type information you need.
I would add that Classes that are called Classes and Data that are called Data and that are parameterized with their content are way too generic.
That saying, your question implies that you are not wanting to fix those flaws, maybe they are out of your control, so you have to live with it :
instead of not loosing the Type information, you ask for a way to retrieve it.
instead of using polymorphism to retrieve the type from the best place to retrieve do so (in my opinion), which is the Start method itself, you ask for a way to retrieve it in the calling code.
So, what I would try to do is :
rework your GetArgsForInstance() method to be able not to loose this information, for instance, replace it by an object, something like :
class DataClassMain : DataClass<InputData,Data>
{
public override void Start(ArgumentProvider argumentProvider)
{
Data argument = argumentProvider.getArgumentAsData(argumentProvider);
base.Start(argument);
}
}
if not possible, retrieve the types from the inside of the derived classes, for instance something like :
public class DataClassMain : DataClass<InputData,Data>
{
public override void Start(object arg)
{
base.Start(arg);
Data argAsData = (Data) arg;
}
}
if not possible, that means you already have a set of constraint that is making your code hard to maintain, so let's go for a messy reflective thing, but you have to be aware that there is no polymorphism involved and get rid of your 'override' and 'virtual' modifier on Start() methods. Here is a fully working program, which output is :
DataClassMain
DataClassAux
public static void Main(string[] args)
{
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object value = GetArgsForInstance(instance);
messyInvoke(instance, value);
}
}
private static void messyInvoke(BaseClass instance, object value)
{
MethodInfo method = instance.GetType().GetMethod("Start");
if (method != null)
{
ParameterInfo[] parametersInfos = method.GetParameters();
if (parametersInfos.Length == 1)
{
object[] paramArray = {value};
method.Invoke(instance, paramArray);
}
}
}
public class BaseClass{
public virtual Type GetTypeOfArgs()
{
return typeof(Toto);
}
}
public class DataPreparationClass<T> : BaseClass {}
public abstract class DataClass<T> : DataPreparationClass<T>
{
}
public class DataClassMain : DataClass<Toto>
{
public void Start(Data arg)
{
Console.WriteLine("DataClassMain");
}
}
public class DataClassAux : DataClass<Toto>
{
public void Start(AuxData argument)
{
Console.WriteLine("DataClassAux");
}
}
private static object GetArgsForInstance(BaseClass isntance)
{
if (isntance is DataClassMain)
return new Data();
if (isntance is DataClassAux)
return new AuxData();
throw new ArgumentException();
}
private static List<BaseClass> GetAllInstance()
{
return new List<BaseClass> {new DataClassMain(), new DataClassAux()};
}
public class Toto{}
public class DataClassInputData
{
}
public class Data : DataClassInputData
{
}
public class AuxData : DataClassInputData
{
}
This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 2 years ago.
I have a generic class. The constructor needs to accept an argument that is another instance of the same class. The problem is that the other instance can have a different generics type.
Looks like C# allows me to have a method with it's own generics type, but this doesn't appear allowed for the constructor.
public class MyClass<T>
{
public MyClass<T2>(MyClass<T2> parent = null)
{
}
// ... Additional stuff
}
The code above tells me T2 is undefined. It doesn't accept it as a method type.
One approach would be to add a second generic type to my class. But this is awkward and, in many cases, the argument will be null and there is not type.
Does anyone see a simple way around this?
Generic constructors aren't allowed. However, you can use a generic factory method instead.
public class MyClass<T>
{
public int Id { get; private set; }
public int? ParentId { get; private set; }
public static MyClass<T> Create(int id)
{
return Create<object>(id, null);
}
public static MyClass<T> Create<T2>(int id, MyClass<T2> parent = null)
{
var current = new MyClass<T>();
current.Id = id;
current.ParentId = parent?.Id;
return current;
}
private MyClass()
{
}
// ... Additional stuff
}
Sample use:
var intClass = MyClass<int>.Create(55);
var charClass = MyClass<char>.Create(234, intClass);
// charClass.ParentId is 55
This is only possible if you do not need to access any generic members of parent outside the factory method. If you do, you'd be better off abstracting it through a non-generic interface or base class.
You are correct. Generic constructors aren't supported.
You could probably try the following:
Create a lower level common interface
public interface IMyClass {
//...some common stuff
IMyClass Parent { get; set; }
}
And use that as the common link between the types
public class MyClass<T> : IMyClass {
public MyClass(IMyClass parent = null) {
Parent = parent;
}
public IMyClass Parent { get; set; }
// ... Additional stuff
}
This question already has answers here:
Keyword 'this' (Me) is not available calling the base constructor
(4 answers)
Closed 9 years ago.
I have the following initialization of a constructor:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, getLocalizedString(this.GetType(), "PageTitle"))
{
}
}
where
public static string getLocalizedString(Type type, string strResID)
{
}
but this.GetType() part causes the following error:
error CS0027: Keyword 'this' is not available in the current context
Any idea how to resolve it?
The 'this' keyword refers to the current instance of the class. In the constructor, you don't have access to the instance because you are about to create one... So try below:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, getLocalizedString(typeof(WizardPage1), "PageTitle"))
{
}
}
The this keyword refers to the current instance of a class, however as you are calling this within the constructor, you don't yet have an instance to refer to (as it is being constructed).
Perhaps an alternate solution would be to have a property in your base class that you can override in the child class. E.g.
public class WizardPage
{
public virtual string PageTitle { get; }
...
}
public class WizardPage1 : WizardPage
{
public override string PageTitle
{
get
{
return getLocalizedString(this.GetType(), "PageTitle");
}
}
}
The key thing here is that you are calling GetType() when you already have an instance of the object.
#Damith is correct on why this doesn't work but one way to deal with this simpler could be to (ignoring implementation specifics):
public abstract class WizardPage
{
// Replace or override existing constructor with this
public WizardPage(int unknownInt, Type currentType, string str)
{
if (currentType == null)
currentType = System.Reflection.MethodBase()
.GetCurrentMethod().GetType();
var localString = getLocalizedString(currentType, str);
// Existing logic here
}
}
And change your child class to:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, this.GetType(), "PageTitle")
{
}
}
Unfortunately, this approach require adding a layer of abstraction if you don't have access to the code of the base class.
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);
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
.NET: Determine the type of “this” class in its static method
How can I make GetType() accessible from a static method?
I have this abstract base class
abstract class MyBase
{
public static void MyMethod()
{
var myActualType = GetType(); // this is an instance method
doSomethingWith(myActualType);
}
}
and an implementation of that class. (I could have many implementations.)
class MyImplementation : MyBase
{
// stuff
}
How can I get myActualType to be typeof(MyImplementation)?
The "type" within a static method is always the specific type, since there is no such thing as a virtual static method.
In your case, this means you can just write:
var myActualType = typeof(MyBase);
Since the "type" of MyMethod, being a static, is always a static method of MyBase.
What about this?
abstract class MyBase<T>
{
public static void MyMethod()
{
var myActualType = typeof(T);
doSomethingWith(myActualType);
}
}
class MyImplementation : MyBase<MyImplementation>
{
// stuff
}
This is the pattern i used.
abstract class MyBase
{
public static void MyMethod(Type type)
{
doSomethingWith(type);
}
}