This cracks my head, I hope somebody will have the wiliness to find a solution.
Right below is a simplified code of the situation. The objective here is, that I wanth a separate, reusable library and to have the option of customizing these classes for each implementation. So i went for inheritance:
namespace Library {
//a class that holds stuff together
public class Core<THandler> where THandler:Handler
{
public THandler handler;
public string text = "Something";
}
//class that react for extern events, say a keyboard events
public class Handler
{
protected object core;
public Handler(object _core) {
core = _core;
}
protected virtual void OnEvent() {
//how to access 'core.text' ??
var a = (Core<Handler>)core; //raises System.InvalidCastException
// since 'core' actualy contains
// an instance of MyCore
}
}
}
namespace MyImplementation {
public class MyCore : Library.Core<MyHandler>
{
}
public class MyHandler : Library.Handler
{
protected override void OnEvent() {
base.OnEvent();
//and what's the preferable option for accessing 'core' here?
var a = (MyCore)core; //I use this
}
}
}
Since Handler.core contains an instance of MyCore, how can one access this object inside Hanlder.OnEventmethod?
You are better off with using interfaces to bind Core and Handler to each other. You can still keep Core<T> generic. Generic type contraints wouldn't allow you to declare circular dependencies, which would otherwise be necessary to make your core work.
Note that the root cause for the problematic cast to be invalid is not that core instance is MyCore from your example, but because MyCore inherits from Core<MyHandler> and not Core<Handler>.
In case, for some reason, you'd insist of keeping the current design, you can make Handler generic as well, passing in its ancestor as type parameter, and fixing the cast like this:
public class Handler<THandler> where THandler : Handler<THandler>
{
protected object core;
public Handler(object _core) {
core = _core;
}
public virtual void OnEvent() {
// this works
var a = (Core<THandler>)core;
}
}
So, to make it a bit more type-safe and avoid casts, the constructor should look like this:
protected Core<THandler> core;
public Handler(Core<THandler> _core) {
core = _core;
}
The MyHandler declaration would then, quite naturally, look like this:
public class MyHandler : Handler<MyHandler>
{
…
}
The best approach here (in my mind, anyway) is to create an interface for the methods and properties that you need to access in Core.
For example, something similar to the following:
namespace Library {
public interface ICore {
string text {get; set;}
}
//a class that holds stuff together
public class Core<THandler> : ICore where THandler : Handler
{
public THandler handler;
private string m_Text = "Something";
public string text
{
get
{
return m_Text;
}
set
{
m_Text = value;
}
}
}
//class that react for extern events, say a keyboard events
public class Handler
{
protected ICore core;
public Handler(object _core) {
core = (ICore)_core;
}
protected virtual void OnEvent() {
Debug.WriteLine(core.text);
}
}
}
namespace MyImplementation {
public class MyCore : Library.Core<MyHandler>
{
}
public class MyHandler : Library.Handler
{
protected override void OnEvent() {
base.OnEvent();
//and what's the preferable option for accessing 'core' here?
var a = (MyCore)core; //I use this
}
}
}
The cast failes because Core is not covariant. Classes in general can not be covariant. Only interfaces and delegates can be covariant.
To reach the expected behaviour you can define the Core class as an interface with a out parameter, like below
public interface ICore<out T>where T:Handler
{
T Handler {get;}
string Text { get; }
}
Related
I'd like to be able to create new generic types using enum values. I believe this is possible with C++ templates, but I don't know if it's possible to do with C#.
So what I'd like to do is:
public class MyClass <T>
{
public void Do<T>() {}
}
public enum Metals
{
Silver, Gold
}
and I'd like to pass in an enum like:
var myGoldClass = new MyClass<Metals.Gold>();
I guess I could create classes called Gold, Silver to achieve this, but I quite like having an enum to constrain the types of my generic class.
The reason I want something like this in the real world is I'm creating an event aggregator (a publish-subscribe model) and I'd want my subscribers to subscribe to messages of a certain type T. So i thought it would be nice if i could have my subscribers subscribe using enums.
EDIT:
To clarify, Metals.Gold is just an example enum. I'd like the client library to create their own enums\classes and use it instead. I'm not defining the enum myself.
Using enum values as generic parameters is not possible. In cases like that you should probably use inheritance:
public abstract class Metal
{
protected Metals MetalType { get; private set; }
protected Metal(Metals metal)
{
MetalType = metal;
}
}
public class Gold : Metal
{
public Gold() : base(Metals.Gold)
{
}
}
Going further, the part of the question about PubSub implementation is too broad as a lot of things should be taken in consideration. Here is an example where you may some useful ideas:
public class EventHub
{
// only one receiver per message type is allowed to simplify an example
private static readonly ConcurrentDictionary<MessageTypes, IReceiver> receivers =
new ConcurrentDictionary<MessageTypes, IReceiver>();
public bool TrySubscribe(MessageTypes messageType, IReceiver receiver)
{
return receivers.TryAdd(messageType, receiver);
}
public void Publish(IMessage message)
{
IReceiver receiver;
if (receivers.TryGetValue(message.MessageType, out receiver))
{
receiver.Receive(message);
}
}
}
public interface IMessage
{
MessageTypes MessageType { get; }
string Text { get; set; }
}
public interface IReceiver
{
void Receive(IMessage message);
}
This is not possible as T as to be a Type and not a value.
Maybe I don't understand your problem but why don't you do something like that :
public class MyClass
{
private readonly Metals _metal;
public MyClass(Metals metal)
{
_metal = metal;
}
public void Do()
{
//using _metal here
}
}
var myGoldClass = new MyClass(Metals.Gold);
Lets say I have a class A which is going to be compiled into a dll to be used later. But I kind of know that later, some methods of class B which I am not aware of its type must be called in A class. The only clue is the name of the methods.
Lets say this is class A:
public class A
{
A(Object instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
Lets say this is class B, happen to be a WinForm:
public B : Form
{
public void ReceiveData(string data)
{
textBox.Append(data + Environment.NewLine);
}
}
Is such approach possible/recommended?
Yes, this is possible using the dynamic keyword (in C# 4.0 or higher). Check the MSDN documentation for more info.
However, this leads to incredibly loose programming and can cause runtime issues that are difficult to debug. You're much better off creating an interface that class B will implement.
public class A
{
A(IDataReceiver instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
public B : Form, IDataReceiver
{
public void ReceiveData(string data)
{
textBox.Append(data + Environment.NewLine);
}
}
public interface IDataReceiver
{
void ReceiveData(string data);
}
You should be using interface. You class B must implement "MyInterface" interface and "MyInterface" should have method which are are expecting A to call.
public class A
{
A(MyInerface instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
If it is not possible to implement interface at class B, you need to use reflection. See here (How to use reflection to call method by name) on how to call a method from a Type (so you will have to pass the type in constructor of A.
It sounds you need to use an interface.
A little information about interfaces can be found here.
Basically you want to create an interface and get it as a parameter for class A and implement it in class B:
interface IDataReceiver
{
void ReceiveData(string data);
}
then class B decleration will look like:
public B : Form, IDataReceiver
And class A` constructor:
A(IDataReceiver dataReceiver)
{
//stuff...
}
Another option here would be to use events. Have your raise an event instead of invoking the callback.
excuse my C#, I'm a little rusty
public class classA {
public event DataReceived(string data);
public void SendProcessedString() {
// you got var data from somewhere
DataReceived(data)
}
}
Then subscribe to that event from your classB
// classB setup code or initializer:
instanceA.DataReceived += dataReceivedHandler;
private void dataReceivedHandler(string data) {
// do something with the data.
}
Yet another method is to use a proper callback - only if a single subscriber is guaranteed. If you need multiple subscribers use an event.
public class classA {
public Action<string> DataReceivedCallback = null;
public void SendProcessedString() {
if (null != DataReceivedCallback) { DataReceivedCallback.Invoke(data); }
}
}
somewhere in classB
instanceA.DataReceivedCallback = new Action<string>(dataReceivedHandler);
private void dataReceivedHandler(string data) {
// do something with the data.
}
I would like to ask what are the risks of having something as follows:
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
protected HtmlTemplateBuilder()
{
LoadTemplates();
}
public abstract void LoadTemplates();
}
The risk is if a derived class derives from the derived class:
DerivedClass2 -> #DerivedClass1 -> HtmlTemplateBuilder
This can be solved by sealing #DerviedClass1, but are there any more risks or better practices for implementing this functionality?
Thanks
The situation in which this pattern bit me is as follows: at some later stage you want to add a specialized HtmlTemplateBuilder, which can load different templates based on some criteria unknown to the class itself (maybe you decide you want some cool templates on a specific day of the year). That is:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public override void LoadTemplates()
{
if (someCondition)
{
LoadTemplatesSet1();
}
else
{
LoadTemplatesSet2();
}
}
}
But how are you going to pass someCondition to the class? The following won't work:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public SpecialHtmlTemplateBuilder (bool someCondition)
{
this.someCondition = someCondition;
}
// ...
}
because the assignment of this.someCondition will be done after calling the base constructor, i.e., after LoadTemplates() is called. Note that sealing derived classes does not solve this problem.
The way to solve this is as #Rahul Misra described: add an explicit Initialize method and call that after the constructor.
Have a look at this link which explains the perils with simple easy to understand examples
https://blogs.msmvps.com/peterritchie/2012/04/25/virtual-method-call-from-constructor-what-could-go-wrong/
I would remove the call to LoadTemplates from constructor and call Initialise on it when the templates actually need to be loaded and used.
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
object locker = new object();
private bool initialised;
protected HtmlTemplateBuilder()
{
}
protected void Initialise()
{
lock (locker)
{
if(initialised)
{
LoadTemplates();
initialised = true;
}
}
}
public abstract void LoadTemplates();
}
I'm trying to create an event delegate where the parameter is strongly typed to match the current class, like this:
public class HPCRequest
{
public delegate void RequestCompleteHandler(HPCRequest request);
public event RequestCompleteHandler RequestComplete;
The problem is that the point of this class is to be inherited, and what I really want is for all those inheriting classes to have the "RequestComplete" event, where the delegate is typed for that class:
public class HPCGetConfig : HPCRequest
{
//I want this class to effectively inherit something like this:
//public delegate void RequestCompleteHandler(HPCGetConfig request);
This is because currently, when I have a function that handles one of my "RequestComplete" events, I currently have to do this:
myGetConfigRequest.RequestComplete += new HPCRequest.RequestCompleteHandler(HPCGetExpectedLosses_RequestComplete);
void HPCGetConfig_RequestComplete(HPCRequest request)
{
HPCGetConfig thisRequest = request as HPCGetConfig;
//This should be strongly typed in the first place.
But I want to be able to do something like this:
request.RequestComplete += new HPCGetConfig.RequestCompleteHandler(HPCGetConfig_RequestComplete);
request.SendRequestAsync();
}
void HPCGetConfig_RequestComplete(HPCGetConfig request)
{
request.RequestComplete -= HPCGetConfig_RequestComplete;
Attempts
I've tried this:
public delegate void RequestCompleteHandler<T>(T request) where T : HPCRequest;
public event RequestCompleteHandler<T> RequestComplete;
but when I try to invoke the event from within the base class using RequestComplete(this);, I get a compile time error: `Delegate 'RequestCompleteHandler' has some invalid arguments.
This happens whether or not I set up the entire HPCRequest class as HPCRequest<T> by going:
public class HPCRequest<T> where T : HPCRequest<T>
{
public delegate void RequestCompleteHandler<T>(T request);
public event RequestCompleteHandler<T> RequestComplete;
public class HPCGetConfig : HPCRequest<HPCGetConfig> { ...
The same error occurs when I try to invoke the event: RequestComplete(this);
I've also tried all forms of creating the delegate and event and overriding them, such as in doing:
public class HPCRequest
{
public delegate void RequestCompleteHandler(HPCRequest request);
public virtual event RequestCompleteHandler RequestComplete;
public sealed class HPCGetConfig : HPCRequest
{
public delegate void RequestCompleteHandler(HPCGetConfig request);
public override event RequestCompleteHandler RequestComplete;
But this gives me a compile time error because I cannot override the RequestComplete event with one of a different delegate type.
Any other ideas?
Edit
Templating the entire HPCRequest class is not an option, after a very thorough attempt, I see that it just screws up every attempt to use the type HPCRequest as a placeholder for any request type. If this solution is going to work, the class HPCRequest must be able to be instantiated and inherited from without specifying a type parameter. I'll need a solution that doesn't require templating HPCRequest.
To make sure everyone know exactly how I'm trying to use this, I pasted some sample code into pastebin that should let you experiment with ways of getting this event templating working without breaking anything. Here it is: http://pastebin.com/bbEYgLj1
What you could try:
public abstract class HPCRequest<T> where T : HPCRequest<T>
{
public delegate void RequestCompleteHandler(T request);
public event RequestCompleteHandler RequestComplete;
protected void RaiseRequestComplete(T request)
{
if (RequestComplete != null)
{
RequestComplete(request);
}
}
}
public class Foo : HPCRequest<Foo>
{
public void Bar()
{
RaiseRequestComplete(this);
}
}
public class Example
{
public static void Test()
{
var request = new Foo();
request.RequestComplete += RequestComplete;
}
static void RequestComplete(Foo request)
{
// It's a Foo!
}
}
This self-referential generic constraint allows what you want I think. I added the protected RaiseRequestCompleted so you can still raise the event from classes that inherit from HCPRequest. Otherwise, only HCPRequest would be allowed to do so.
UPDATE: I updated the code to pass this and added sample code that matches your desired result.
You can use generic type parameter for this purposes so each class inherited from HPCRequest must specify a generic type parameter. Also I would suggest marking classes which are designed to be a base class by abstract modifier to avoid explicit instantiation:
public abstract class HPCRequest<TRequest>
where TRequest: class
{
public delegate void RequestCompleteHandler(TRequest request);
public event RequestCompleteHandler<TRequest> RequestComplete;
}
public sealed class HPCGetConfig : HPCRequest<HPCGetConfig>
{
}
You can constrain the type parameter of the abstract class to be derived from the abstract class itself. It seems strange, but you can set it up like this:
public abstract class HPCRequest<T> where T : HPCRequest<T>
{
public delegate void RequestCompleteHandler(T request);
public event RequestCompleteHandler RequestComplete;
}
public class DerivedHPCRequest : HPCRequest<DerivedHPCRequest>
{
}
Your use case is a great candidate for explicitly implementing a non-generic interface in a generic base class. I'm not certain that I am completely understanding the desired functionality, but I think I did. I wrote some code (below) that should get you started.
As a side note, there isn't a real reason to declare the delegates. For consistency with MSDN Event Design standards, your solution would use EventHandler<T> and a custom EventArgs implementation.
Code
// this is a sample program using the pattern i am recommending
// I'm pretty sure this is what you wanted your code to look like?
public class Program
{
public static void Main()
{
var request = new HPCGetConfig();
request.RequestComplete += HandleConfigRequestCompleted;
request.SendAsync();
}
static void HandleConfigRequestCompleted(object sender, RequestCompleteEventArgs<HPCGetConfig> e)
{
var request = e.Request;
// do something with the request
}
}
// the non-generic event args class
public abstract class RequestCompleteEventArgs : EventArgs
{
public abstract Type RequestType { get; }
public abstract object RequestObject { get; set; }
}
// the generic event args class
public class RequestCompleteEventArgs<T> : RequestCompleteEventArgs
{
private T m_Request;
public T Request
{
get { return m_Request; }
set { m_Request = value; }
}
public override Type RequestType
{
get { return typeof(T); }
}
public override object RequestObject
{
get { return Request; }
set
{
if (!(value is T))
{
throw new ArgumentException("Invalid type.", "value");
}
m_Request = (T)value;
}
}
}
// the non-generic interface
public interface IHPCRequest
{
event EventHandler<RequestCompleteEventArgs> RequestComplete;
}
// the generic base class
public abstract class HPCRequest<T> : IHPCRequest
where T : HPCRequest<T>
{
// this sanitizes the event handler, and makes it callable
// whenever an event handler is subscribed to the non-generic
// interface
private static EventHandler<RequestCompleteEventArgs<T>> ConvertNonGenericHandler(EventHandler<RequestCompleteEventArgs> handler)
{
return (sender, e) => handler(sender, e);
}
// this object is for a lock object for thread safety on the callback event
private readonly object Bolt = new object();
// This determines whether the send method should raise the completed event.
// It is false by default, because otherwise you would have issues sending the request asynchronously
// without using the SendAsync method.
public bool AutoRaiseCompletedEvent { get; set; }
// This is used to ensure that RequestComplete event cannot fire more than once
public bool HasRequestCompleteFired { get; private set; }
// declare the generic event
public event EventHandler<RequestCompleteEventArgs<T>> RequestComplete;
// explicitly implement the non-generic interface by wiring the the non-generic
// event handler to the generic event handler
event EventHandler<RequestCompleteEventArgs> IHPCRequest.RequestComplete
{
add { RequestComplete += ConvertNonGenericHandler(value); }
remove { RequestComplete -= ConvertNonGenericHandler(value); }
}
// I'm not 100% clear on your intended functionality, but this will call an overrideable send method
// then raise the OnRequestCompleted event if the AutoRaiseCompletedEvent property is set to 'true'
public void Send()
{
SendRequest((T)this);
if(AutoRaiseCompletedEvent)
{
OnRequestCompleted((T)this);
}
}
public void SendAsync()
{
// this will make the event fire immediately after the SendRequest method is called
AutoRaiseCompletedEvent = true;
new Task(Send).Start();
}
// you can make this virtual instead of abstract if you don't want to require that the Request
// class has the Send implementation
protected abstract void SendRequest(T request);
// this raises the RequestCompleted event if it is the first call to this method.
// Otherwise, an InvalidOperationException is thrown, because a Request can only
// be completed once
public void OnRequestCompleted(T request)
{
bool invalidCall = false;
Exception handlerException = null;
if (HasRequestCompleteFired)
invalidCall = true;
else
{
lock(Bolt)
{
if(HasRequestCompleteFired)
{
invalidCall = true;
}
else
{
if (RequestComplete != null)
{
// because you don't want to risk throwing an exception
// in a locked context
try
{
RequestComplete(this, new RequestCompleteEventArgs<T> { Request = request });
}
catch(Exception e)
{
handlerException = e;
}
}
HasRequestCompleteFired = true;
}
}
}
if(invalidCall)
{
throw new InvalidOperationException("RequestCompleted can only fire once per request");
}
if(handlerException != null)
{
throw new InvalidOperationException("The RequestComplete handler threw an exception.");
}
}
}
// a sample concrete implementation
public class HPCGetConfig : HPCRequest<HPCGetConfig>
{
protected override void SendRequest(HPCGetConfig request)
{
// do some configuration stuff
}
}
I think that you would have to create an abstract base class that can of cause not be instantiated:
public abstract class HPCRequestBase<T> where T : HPCRequestBase<T>
{
public delegate void RequestCompleteHandler(T request);
public event RequestCompleteHandler RequestComplete;
protected void OnRequestComplete(T request)
{
if (RequestComplete != null) {
RequestComplete(request);
}
}
public void Test( )
{
OnRequestComplete((T)this);
}
}
public class HPCRequest : HPCRequestBase<HPCRequest>
{
public void Test2()
{
OnRequestComplete(this);
}
}
public class HPCRequestConfig : HPCRequestBase<HPCRequestConfig>
{
// Derived from the base class, not from HPCRequest
}
Also 'this' has to be casted to T: OnRequestComplete((T)this);
This test runs without an error:
var hpcr = new HPCRequest();
hpcr.Test();
hpcr.Test2();
It's can't be done.
I've ended up having to cast the delegate everywhere it's used.
Happy to change the accepted answer if anything ever shows otherwise.
I have a base class which has a nested type, inside. There's a function in the outer (base) type which would be overridden by it's children later. In fact this function belongs to the inner type from the OO prespective but still I need it, to be overridden by subtypes of the base class.
Should I use this function as a callback from the inner type or just move it inside the inner type and let's the subtypes to override it from there?
EDIT: Sample code added
class A
{
protected void func() { /* do something */ }
class B { /**/ }
}
// OR
class A
{
class B
{
protected void func() { /* do something */ }
}
}
// Then
class C : A
{
override func() { /**/ }
}
My suggestion is to crate a delegate for the inner type function which is initiated by the constructor of the base class:
internal class BaseClass
{
public BaseClass(Action myAction)
{
this.innerType = new InnerType(myAction);
}
public BaseClass()
{
// When no function delegate is supplied, InnerType should default to
// using its own implementation of the specific function
this.innerType = new InnerType();
}
}
As you see, deriving types can call the base constructor with :base (overridenAction) where they can provide their own implementation of the function right to the innermost type. Of course, you are not obligated to use Action but any delegate you want.
IMO what you are describing looks like The Strategy design pattern. Consider using this pattern. Your code would be much more maintainable as it contains well recognizable pattern. You also can take a look at state design pattern, usually you have to choose between these two, they are closely connected.
In this scenario:
class A
{
class B
{
protected void func() { // do something }
}
}
You cannot derive from class A and override func() in class B.
From your description it seems that A-derived classes should be able to override some function (or functionality) in the inner class B which indicates that you maybe should rethink your design. Either extract B and don't make it an inner class or make the functionality you want to override an explicit dependency via an interface like this:
class A
{
private B _MyB;
public A(ISomeBehaviour behaviour)
{
_MyB = new B(behaviour);
}
}
In anyway if you want to stick with your design then I would not recommend the delegate approach and rather choose the override because with the delegates it makes it harder to add decoration if that is all you need in your child classes.
This is how the outer class can serve as a strategy to the inner service class.
Note that using pattern names such as TemplateMethod and Strategy as real class names is not recommended, use whatever is meaningful in the domain. Same applies to Outer and Inner.
public class Consumer
{
public void Foo()
{
IOuterFoo fooService = new Derived();
fooService.OuterFoo();
}
}
// ...
public interface IOuterFoo
{
void OuterFoo();
}
abstract class Base : Base.IStrategy, IOuterFoo
{
public void OuterFoo() { _service.Foo(); }
private readonly InnerService _service;
protected Base() { _service = new InnerService(this); }
private interface IStrategy { void Foo(); }
private class InnerService
{
private readonly IStrategy _strategy;
public InnerService(IStrategy strategy) { _strategy = strategy; }
public void Foo() { _strategy.Foo(); }
}
void IStrategy.Foo() { TemplateMethodFoo(); }
protected abstract void TemplateMethodFoo();
}
class Derived : Base
{
protected override void TemplateMethodFoo()
{
throw new NotImplementedException();
}
}