This one's a little weird/complex and more just curiosity than anything.
I was looking for a way to make sure static calls from a base class could safely use static information set up in a derived class. I then noticed that C# allows me to call the derived class static constructor in the base class static constructor.
My question: Is is safe to call the derived class static constructor in the base class static constructor
Here is some sample code:
public abstract class Enumeration<TEnum, TValue>
where TEnum : Enumeration<TEnum, TValue> // << Note the CRTP-ish thing
where TValue: class
{
private static readonly Dictionary<string, Enumeration<TEnum, TValue>> Mapping = new Dictionary<string, Enumeration<TEnum, TValue>>();
public TValue Value { get; }
public string Name { get; }
// Base class calling derived static constructor. This sets up "Mapping" with derived class enumerations
static Enumeration()
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(TEnum).TypeHandle);
}
// Static member "Mapping" filled using this constructor when derived class statics are initialized
protected Enumeration(TValue enumValue, string name)
{
Value = enumValue;
Name = name;
Mapping.Add(name, this);
}
// Uses "Mapping", so "Mappings" needs to be filled before this is called.
protected static IEnumerable<TEnum> All => Mapping.Values.AsEnumerable().Cast<TEnum>();
public override string ToString() { return Name; }
}
public sealed class DerivedEnum : Enumeration<DerivedEnum, String>
{
// This static member will input itself into the static "Mapping" in the base class
public static readonly DerivedEnum A = new DerivedEnum("A", "A");
private DerivedEnum(string val, string name) : base(val, name) {}
}
I have done several basic tests and it doesn't seem to break. Is there a way this could break?
Here is a fiddle if you need to... fiddle: https://dotnetfiddle.net/mREPyL
Also, my code is inspired by this answer. I wanted to see if I could get the derived classes more succinct.
Related
I want to force my child classes to pass themselves as as the generic parameter to the parent class.
For example :
class BaseClass<T> where T: BaseClass
{
//FullClassName : Tuple [Save,Update,Delete]
Dictionary<string,Tuple<delegate,delegate,delegate>> dict = new Dictionary...;
static BaseClass()
{
RegisterType();
}
private static void RegisterType()
{
Type t = typeof(T);
var props = t.GetProperties().Where(/* Read all properties with the SomeCustomAttribute */);
/* Create the delegates using expression trees and add the final tuple to the dictionary */
}
public virtual void Save()
{
delegate d = dict[t.GetType().FullName];
d.Item1(this);
}
}
class ChildClass : BaseClass<ChildClass>
{
[SomeCustomAttribute]
public int SomeID {get;set;}
[SomeCustomAttribute]
public string SomeName {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
ChildClass c = new ChildClass();
c.Save();
}
}
Obviously the above code won't compile. I'll restate : I want the child class to pass itself as the generic parameter and not any other child of BaseClass.
(The above code is kind of a psuedo code and will still not compile).
You can do this:
public class BaseClass<T> where T: BaseClass<T> { }
public class ChildClass : BaseClass<ChildClass> { }
But this doesn't force you to use ChildClass as the generic parameter. You could do this public class OtherChildClass : BaseClass<ChildClass> { } which would break the "coontract" that you want to enforce.
The direct answer is that if your accessing a static method then typeof(T) will give you the type for reflection.
However, there is probably better solutions than using reflection. Options:
1) Static constructor on the child class.
2) Abstract method declared in the base class.
I do not know the application, but I get concerned about my design if I feel like using a static constructor, I also get concerned if a base class needs to initialize the child class.
I suggest looking at injection as a solution rather than inheritance. It offers superior unit testing and often a better architecture.
More info (after initial post), this is my preferred solution:
public interface IRegesterable
{
void Register();
}
public class Widget : IRegesterable
{
public void Register()
{
// do stuff
}
}
public class Class1
{
public Class1(IRegesterable widget)
{
widget.Register();
}
}
Hope this helps
The ConcurrentDictionary is being used as a Set<Type>. We can check in the Set<Type> if the type has been initialized. If not we run RegisterType on the type.
public abstract class BaseClass
{
//Concurrent Set does not exist.
private static ConcurrentDictionary<Type, bool> _registeredTypes
= new ConcurrentDictionary<Type, bool>();
protected BaseClass()
{
_registeredTypes.GetOrAdd(GetType(), RegisterType);
}
private static bool RegisterType(Type type)
{
//some code that will perform one time processing using reflections
//dummy return value
return true;
}
}
public class ChildClass : BaseClass
{
}
There are several inefficiencies with this pattern though.
object.GetType() is pretty darn slow, and inefficient.
Even with the HashSet behavior, we are checking for initialization on each instanciation. Its as fast as I can get it, but its still pretty superfluous.
I tried to search for solutions, but my problem is I don't even know what terms to use. Generics, Delegates, LINQ, Reflection, and Abstract ideas could be part of the solution, but my "Google-fu" isn't turning up the right answer.
Question:
I have multiple classes (ClassA, ClassB, ClassC) that all have the same 2-3 properties DoThisA, DoThisB, DoThisC.
The way the code works is that I always want to do the same code to set DoThisA, DoThisB, and DoThisC when I process each of the classes.
For example, to simplify, the logic will always be:
{some computations to set string currentValueImProcessing to something}
if (xyz) [ClassA|B|C].DoThisA = currentValueImProcessing
else [ClassA|B|C].DoThisB = currentValueImProcessing
I don't want to write those same statements over and over, so how do I just send a reference to the class (A,B,C) to a method to do the logic?
If it was written correctly each of ClassA, ClassB, and ClassC would have implemented some generic class and I could use that, but I cannot. Each of the classes are independent but have the same named properties.
Any guidance on concepts/code?
Thanks!
Create an interface for your properties:
internal interface IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
Then, make your classes implement it:
public class ClassA : IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
public class ClassB : IDoThis
{
// Same properties
}
public class ClassC : IDoThis
{
// Same properties
}
This, way, you'll be able to create a static initializer method somewhere:
internal static class MyClassesExtensions
{
public static void InitTheStuff(this IDoThis obj)
{
// Do something here, for example:
if (String.IsNullOrEmpty(obj.DoThisA))
obj.DoThisA = "foo";
else
obj.DoThisB = obj.DoThisC;
}
}
And then you can just call this.InitTheStuff() anywhere from ClassA, ClassB and ClassC.
you can either use reflection or you can use dynamic (dynamic will use reflection for you)
dynamic obj = new ClassA();
obj.DoTHisA();
is how to do it with dynamic
I am assuming that you are talking about classes that you intend to instantiate. If DoThisA,B,C are static methods then you must use reflection
NOTE - if you can change the classes then add an interface as others have suggested, or even a common base class
The reflection one looks like this
var type = obj.GetType(); // obj is ClassX object
var method = type.GetMethod("DoTHisA");
method.Invoke(obj);
I have not checked this - so the syntax might be a bit off - but this is the basic mechanics of reflection method calling. YOu need to get fancier if there are multiple methods with the same name, if the methods takses params etc
There are at least four options open to you - maybe more.
Create an interface, which is implemented by all of your classes and that includes the common methods.
Create a base class from which all classes inherit. The common functionality can then be implemented in the base class. If the implementation differs depending on the clases, but you can define common signatures for the methods, make your base class an the common funtionality abstract. You then can implement the actual functionality in each of your classes.
Use a dynamic object as in #pm100's solution.
Use reflection to access the common functionality.
As a guidance methods 1. and 2. are to be preferred, as they allow your code to be checked on compile time. If, however, you do not have control over the classes that contain the common functionality - for example you do not have access to the source code or you are permitted to make changes to the code - you can use the other two methods.
If you'd ask me which of the two I would prefer, I guess that I would go for 3. over 4. But this is personal preference.
Prob you are talking about inheritance.
For your task you need a base abstract class with general properties:
public abstract class Base
{
public bool DoThisA { get; set; }
public bool DoThisB { get; set; }
}
and child classes:
public class A : Base { }
public class B : Base { }
public class C : Base { }
After that you can create a method which will accept object of type Base
public void Do(Base b, bool xyz, bool currentValueImProcessing)
{
if (xyz)
{
b.DoThisA = currentValueImProcessing;
}
else
{
b.DoThisB = currentValueImProcessing;
}
}
There are already many methods provided here, so just for the sake of completeness... Here's some runtime code generation:
public class ClassA
{
public string DoThisA { get; set; }
public int DoThisB { get; set; }
public bool DoThisC { get; set; }
public void Init()
{
// You can call this from anywhere, even from an unrelated class
MyClassInitializer<ClassA>.Init(this);
}
}
public static class MyClassInitializer<T>
{
// Create the getters/setters you need, and make sure they're static.
private static readonly Func<T, string> _getA = BuildGetter<string>("DoThisA");
private static readonly Action<T, string> _setA = BuildSetter<string>("DoThisA");
private static readonly Func<T, int> _getB = BuildGetter<int>("DoThisB");
private static readonly Action<T, int> _setB = BuildSetter<int>("DoThisB");
private static readonly Func<T, bool> _getC = BuildGetter<bool>("DoThisC");
private static readonly Action<T, bool> _setC = BuildSetter<bool>("DoThisC");
private static Func<T, TValue> BuildGetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, TValue>>(Expression.Property(obj, name), obj).Compile();
}
private static Action<T, TValue> BuildSetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(TValue));
return Expression.Lambda<Action<T, TValue>>(Expression.Assign(Expression.Property(obj, name), value), obj, value).Compile();
}
public static void Init(T obj)
{
// Here's your custom initialization method
if (_getA(obj) == "Foo")
_setB(obj, 42);
else
_setC(obj, true);
}
}
Not necessarily the easiest one to grasp, but this should be much faster than using dynamic or reflection. That said, if you don't need the speed, stick with dynamic as it's easier.
I've got two problems. One is that I'm trying to have an abstract singleton class, that has the singleton functionality + a little extra functionality in it, but this class is also a generic (unrelated to it being singleton). I want any of it's child classes to inherit the singleton functionality without rewriting code, and also the rest of the functionality which is dependent on the generic type.
Second problem, the abstract class has a non-default constructor, that should receive a string value. This string can be determined by the class of the child-class (the class that inherits the abstract calss).
My ideas to handle this where as follows:
Add an abstract static method to the abstract class that returns a string parameter, so that every derived class will implement it, hence any non-abstract instance of the class will work fine. Not possible because static methods cannot be abstract.
Create an interface with a static method that returns the string, and make sure that the generic type inherits from that interface. Then when instantiating the singleton, it will call T.GetTheString() to pass as a parameter to the constructor. Not possible since interfaces may not have static methods.
Any ideas?
Here's some simplified code that explains my problem:
public abstract class NamedObject<T> {
private static NamedObject<T> _instance;
public static NamedObject<T> Instance {
get {
if (_instance == null) {
_instance = new NamedObject<T>("Need to determine this string from the non-abstract child class of NamedObject");
}
return _instance;
}
}
private string objectName;
public NamedObject(string objectName) {
this.objectName = objectName;
}
public string GetFullName() {
return objectName + "(" + GetClassName() + ")";
}
protected virtual string GetClassName() {
return typeof(T).ToString();
}
}
Note that I need the generic T for GetClassName(), and note that to create an instance of the singleton, I need to call a static method of the child class that inherits this class (which seems to be impossible)
Edit: Updated the question to better reflect my problems.
Edit: Thanks for everyone's help. The solution for the second issue was to use a default constructor, and get the string that was supposed to be a parameter within the constructor from a non-static method of the child class (abstract in the base class).
In addition, my entire idea of Singleton inheritance was wrong, which I managed to fix thanks to Rob Lyndon's answer.
Here's the final code (I know it doesn't make sense, this is just a simplified version...):
public abstract class NamedObject<ME, T> where ME : NamedObject<ME, T>, new()
{
private static NamedObject<ME, T> _instance;
public static NamedObject<ME, T> Instance {
get {
if (_instance == null) {
_instance = new ME();
}
return _instance;
}
}
private string objectName = "test";
public NamedObject() {
this.objectName = GetObjectName();
}
public string GetFullName() {
return objectName + "(" + GetClassName() + ")";
}
protected virtual string GetClassName() {
return typeof(T).ToString();
}
protected abstract string GetObjectName();
}
And the child class:
public sealed class MyNamedObject : NamedObject<MyNamedObject, MyClass>
{
public MyNamedObject() : base() {
}
protected override string GetObjectName () {
return "MyName";
}
}
So when calling MyNamedObject.Instance for the first time, it will NamedObject() constructor, with MyClass as T, and the objectName parameter will be "MyName" as defined by the child class MyNamedObject.
Exactly what I was looking for. Thanks for everyone's help this was very helpful.
Don't do singletons. Ever.
Anyway, here is one way of doing them that comes close to your use case.
// base class
public abstract class NamedObject<ME, T> where ME : NamedObject<ME, T>, new()
{
private static NamedObject<ME, T> _instance;
public static NamedObject<ME, T> Instance
{
get
{
if (_instance == null)
{
_instance = new ME { objectName = GetLabel(typeof(T)) };
}
return _instance;
}
}
private string objectName;
public string GetFullName()
{
return objectName + "(" + GetClassName() + ")";
}
protected abstract string GetLabel(Type type);
protected abstract string GetClassName();
}
I suggest you introduce an attribute which you decorate each type with, and extract that when you need to. You won't be able to validate at compile-time that the type has the right type, but there's not a lot you can do about that. Unit test all the types you'll need it for :)
[AttributeUsage(AttributeTargets.Class)]
public class NameAttribute : Attribute
{
public NameAttribute(string name)
{
this.Name = name;
}
public string Name { get; set; }
}
[Name("Foo")]
public class SomeClass
{
}
Then in your singleton class, use a static constructor instead of having a thread-unsafe property.
private static readonly NamedObject<T> instance;
static NamedObject()
{
// TODO: Validation :)
var attributes = typeof(T).GetCustomAttributes(typeof(NameAttribute), false);
var firstAttribute = ((NameAttribute[]) attributes)[0];
string name = firstAttribute.Name;
instance = new NamedObject<T>(name);
}
public static NamedObject<T> Instance { get { return instance; } }
Or use Lazy<> instead. See my article on singletons for more information on that side of things.
EDIT: To clarify - you shouldn't have NamedObject as an abstract class to start with. Singletons and inheritance simply don't mix. NamedObject<T> should be a sealed class instead, which has a single instance of any T. It doesn't enforce that there's only one instance of T created.
This should do what you want (the Name property could also be an abstract method, seems better as a property if we're going with the singleton pattern).
class Program
{
static void Main(string[] args)
{
Console.WriteLine(MyNamedObject.Instance.Name);
}
}
public abstract class NamedObject<T> where T : NamedObject<T>, new()
{
private static T _instance;
public abstract string Name { get; }
public static T Instance
{
get { return _instance ?? (_instance = new T()); }
}
}
public class MyNamedObject : NamedObject<MyNamedObject>
{
public override string Name
{
get { return "My Named Object Name"; }
}
}
abstract class DirectiveNode
{
public static readonly RequirementOptions ArgumentOptions = RequirementOptions.Optional;
}
class IfNode : DirectiveNode
{
static IfNode()
{
ArgumentOptions = RequirementOptions.Required; // error here
}
I don't understand the problem. I thought static IfNode() was a static constructor? Why the error?
Just found this: Assigning to static readonly field of base class
You can only assign it in the static constructor of the same class.
By the way, it sounds like you expect the static field to contain different values depending on which derived class you are talking about. This is not how it works. Only a single instance of the field will exist and it's shared across all derived classes.
Unlike nonstatic constructors, a subclass's static constructor has no relationship with the parent static constructor. If you want the subclass to be able to change the ArgumentOptions value used by base class functions, consider a virtual property:
abstract class DirectiveNode
{
public virtual RequirementOptions ArgumentOptions
{
get { return RequirementOptions.Optional; }
}
}
class IfNode : DirectiveNode
{
public override RequirementOptions ArgumentOptions
{
get { return RequirementOptions.Required; }
}
}
This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 2 years ago.
Assume the following code (Please read my question in the code comments in the final class):
//This is my Generic Class
public class ClientRequestInfo<K, V>
{
public string Id { get; set; }
private Dictionary<K, V> parameters;
public ClientRequestInfo()
{
parameters = new Dictionary<K, V>();
}
public void Add(K key, V value)
{
parameters.Add(key, value);
}
}
public class ProcessParameters()
{
private void CreateRequestAlpha()
{
ClientRequestInfo<int, string> info = new ClientRequestInfo<int, string>();
info.Add(1, "Hello");
SynchRequest s = new SynchRequest(info);
s.Execute();
}
private void CreateRequestBeta()
{
ClientRequestInfo<int, bool> info = new ClientRequestInfo<int, bool>();
info.Add(1, true);
SynchRequest s = new SynchRequest(info);
s.Execute();
}
}
public class SynchRequest
{
//What type should I put here?
//I could declare the class as SynchRequest<K, V> but I don't want
//To make this class generic.
private ClientRequestInfo<????,?????> info;
private SynchRequest(ClientRequestInfo<?????,?????> requestInfo)
{
//Is this possible?
this.info = requestInfo;
}
public void Execute()
{}
}
If you don't want to make SynchRequestInfo generic, can you make a non-generic base class for ClientRequestInfo? --
public abstract class ClientRequestInfo
{
public abstract void NonGenericMethod();
}
public class ClientRequestInfo<K, V> : ClientRequestInfo
{
public override void NonGenericMethod()
{
// generic-specific implementation
}
}
Then:
public class SynchRequest
{
private ClientRequestInfo info;
private SynchRequest(ClientRequestInfo requestInfo)
{
this.info = requestInfo;
}
public void Execute()
{
// ADDED: for example
info.NonGenericMethod();
}
}
The class has to be generic if you want generic member variables.
private ClientRequestInfo<????,?????> info;
Is a generic member.
You can use a non-generic base class or interface:
class ClientRequestInfo<K,Y> : IClientRequestInfo
But in your example, ClientRequestInfo doesn't have any non-generic members, so the interface/base class would be empty and have to be casted to the correct generic version to be useful anyway.
You have two options, if you want to not make SynchRequestInfo generic.
Make a non-generic base class, having both use it.
Provide an interface to use, such as ISynchInfo, and have your generic class implement the interface.
In this case, I'd prefer the interface approach, since you may want to synchronize other types (separate from client requests) in the future.
Make ClientRequestInfo(K,V) implement a ClientRequestInfo interface with the interface functions SynchRequest will needs.