c# generic delegate to manage instantiated objects - c#

I'm trying to figure out how to use a generic delegate to manage my instantiated objects in a game engine.
Here is some pseudo-code to demonstrate what I'm trying to do:
public class ObjectManager
{
public delegate void ObjectManagerEvent <T> (T instantiatedObject);
public ObjectManagerEvent <T> onObjectInstantiated;
public void InstantiateObject (Object objToInstantiate)
{
var obj = SomeInternalInstantiateMethod ();
ObjectManagerEvent _onObjectInstantiated = onObjectInstantiated;
if (_onObjectInstantiated != null)
{
_onObjectInstantiated (obj);
}
}
}
public class Shape : EBehaviour {}
public class Animal : EBehaviour {}
public class DemoShape
{
private void Init ()
{
ObjectManager.onObjectInstantiated += OnObjectInstaniated;
}
public void OnObjectInstaniated (Shape shape)
{
// do something with shape
}
}
public class DemoAnimal
{
private void Init ()
{
ObjectManager.onObjectInstantiated += OnObjectInstaniated;
}
public void OnObjectInstaniated (Animal animal)
{
// do something with animal
}
}
I know that public ObjectManagerEvent <T> onObjectInstantiated (); would throw an error, but I'm just kind of lost on how to achieve what I want.
Any pointers?

First, your delegate syntax is very C# 1.0.
Option 1
You can't do this in a particularly simple and elegant way because in C# you cannot use an open generic type to declare a generic event. The closest that we can do is create a dictionary of objects, each of which has an event, and we can use generic methods to access this dictionary.
I also assume you intend InstantiateObject to create and return a new instance. Here I also assume everything is a class with a parameterless constructor.
public static class ObjectManager
{
public class TypeEvent<T>
{
// Our event handler will accept a parameter of type T and return void
public event Action<T> OnObjectInstantiated;
public void RaiseObjectInstantiated(T obj)
{
OnObjectInstantiated?.Invoke(obj);
}
}
private static Dictionary<Type, object> _typeMap = new Dictionary<Type, object>();
public static TypeEvent<T> ForType<T>() where T: class, new()
{
Type t = typeof(T);
if (!_typeMap.ContainsKey(t))
{
_typeMap[t] = new TypeEvent<T>();
}
return _typeMap[t] as TypeEvent<T>;
}
public static T InstantiateObject<T>() where T: class, new()
{
T obj = new T();
ForType<T>().RaiseObjectInstantiated(obj);
return obj;
}
}
You could use it like so:
ObjectManager.ForType<Foo>().OnObjectInstantiated += fooInstantiated;
Foo f = ObjectManager.InstantiateObject<Foo>();
Option 2
If you are okay with making ObjectManager itself a static generic class, you could greatly simplify this. Note this means you no longer have just one ObjectManager class - ObjectManager<Foo> and ObjectManager<Bar> are now different classes with different variables. If that's acceptable to you, this makes things a lot cleaner for the small bit you've told us that ObjectManager needs to do:
public static class ObjectManager<T> where T : class, new()
{
// Our event handler will accept a parameter of type T and return void
public static event Action<T> OnObjectInstantiated;
public static T InstantiateObject()
{
T obj = new T();
OnObjectInstantiated?.Invoke(obj);
return obj;
}
}

Related

How to pass 2 different types into a function param in c#?

In c# if I have this
private void Run(Web site) {
site.BreakRoleInheritance(false, false);
}
private void Run(ListItem folder) {
folder.BreakRoleInheritance(false, false);
}
How can I instead make 1 function that can accept either Site or Folder?
If Site and Folder are classes that you've created, then you can create a common interface which those classes inherit from. For example:
public interface IBreakable
{
void break();
}
public class Folder : IBreakable
{
public void break() { /* implementation here*/ }
}
public class Site : IBreakable
{
public void break() { /* implementation here*/ }
}
Usage
private void Run(IBreakable breakable)
{
breakable.break();
}
Edit
Here's a solution based on reflection, although this is not ideal.
void Run(object obj)
{
MethodInfo method = obj.GetType().GetMethod("break");
if (!(method is null))
{
method.Invoke(obj, new object[] {});
}
}
Given
public class Foo
{
public void break() {Console.WriteLine("Foo");}
}
public class Bar
{
public void break() {Console.WriteLine("Bar");}
}
public class Bad
{
public void NotBreak() {Console.WriteLine("Bad");}
}
Usage
Foo foo = new Foo();
Bar bar = new Bar();
Bad bad = new Bad();
Run(foo);
Run(bar);
Run(bad);
Output
Foo
Bar
As a later answer from #Pedro pointed out, those specific classes derive from a common ancestor, and that would be the preferred option. Assuming you did not have that option:
You can use the C# dynamic type (sorry if that is not the latest doc, I couldn't find a newer one):
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic
Example:
using System;
public class Program
{
public static void Main()
{
var foo = new Foo();
var bar = new Bar();
DoSomething(foo);
DoSomething(bar);
}
private static void DoSomething<T>(T someObjectWithDoMethod)
{
((dynamic)someObjectWithDoMethod).Do();
}
}
public class Foo
{
public void Do() { Console.WriteLine("Foo is doing something"); }
}
public class Bar
{
public void Do() { Console.WriteLine("Bar is doing something"); }
}
.Net Fiddle: https://dotnetfiddle.net/MShLK5
Based on your comments to other answers, Web and ListItem are types defined in the Microsoft.SharePoint.Client.
Checking the SDK docs, both types derive from SecurableObject where the BreakRoleInheritance method is defined.
That being the case, all you need to do is define one method that takes a SecurableObject object as an input:
public void Run(SecurableObject item)
{
item.BreakRoleInheritance();
}
And you should be able to pass a Web and a ListItem to this same method.

Unity3D C# abstract class with static instance creation not working

Hello I am working on a objectpooling class has T "ObjectPooling".
And made a child class. So I want to make automatic singleton for this class. So if I use "instance" it should check if m_instance is null. If yes "spawn" the script and assign m_instance.
public abstract class ObjectPooling<T> : MonoBehaviour
{
public static float start = 30;
public static bool extendable = true;
public List<T> objects = new List<T>();
public abstract T getNext();
public abstract void Add(T obj);
static T m_instance;
public static T instance
{
get
{
return m_instance ?? (m_instance = CreateInstance());
}
}
protected static T CreateInstance()
{
GameObject g = new GameObject("ObjectPooling");
var c = g.AddComponent<T>();
return c;
}
}
The problem is at the last lines in the CreateInstance().
It says
An implicitly typed local variable declaration cannot be initialized
with `UnityEngine.GameObject.AddComponent(System.Type)'
I am not sure what can I do here now. I tried with ObjectPooling before but thats gives no error but also is not working.
So my goal is that the child has also singleton. I did it currently manually but want I want to later should be like this (ofc the base class should do it instead of child class but still check it).
public class BulletPooling : ObjectPooling<BulletBase>
{
public override void Add(BulletBase obj)
{
if(extendable)
objects.Add(obj);
}
public override BulletBase getNext()
{
for(int i = 0; i < objects.Count; i++)
{
var bs = objects[i];
if (!bs.gameObject.activeInHierarchy)
return bs;
}
return null;
}
// this part
static BulletPooling m_instance;
public static BulletPooling instance
{
get
{
return m_instance ?? (m_instance = CreateInstance());
}
}
protected static BulletPooling CreateInstance()
{
GameObject g = new GameObject("ObjectPooling");
var c = g.AddComponent<BulletPooling>();
return c;
}
}
You can see here I am working with new Childclass which has T = BulletBase
This is because GameObject.AddComponent requires an object of a specific type, rather than "any type". In your ObjectPooling class, you only specify that it can be an object of any type, and the compiler cannot infer which types you are using beforehand.
AddComponent is kind of a nasty function, since you can also pass it a string, which should be the name of a script class.
You could specify the type that T must adhere to as UnityEngine.Component to get around this. that would look like this :
public abstract class ObjectPooling<T>: MonoBehaviour where T : UnityEngine.Component
{
public static float start = 30;
public static bool extendable = true;
public List<T> objects = new List<T>();
public abstract T getNext();
public abstract void Add(T obj);
static T m_instance;
public static T instance
{
get
{
return m_instance ?? (m_instance = CreateInstance());
}
}
protected static T CreateInstance()
{
GameObject g = new GameObject("ObjectPooling");
//this is where your compiler could not tell if T was the correct type by the way...
var c = g.AddComponent<T>();
return c;
}
}
but that might break the functionality of adding scripts as game components using a string with their name. (though i think in your case, it won't be a problem)

Generic message handlers

I want to create a generic mechanism for handling messages in C#. I have a need for this in my small application, so I don't want to use full blown message bus. My requirements are quite simple:
I want to have a couple of classes for messages i.e. Message1, Message2. They can inherit from one base class, that's not a problem, but if they don't I don't care. Currently they do inherit from Message.
be able to get handler for each and every message class. i.e. if I send Message1, then Message1Handler class should be instantiated. Handlers have to implement IMessageHandler<T> where T is the message class. IMessageHandler is defined as follows:
interface IMessageHandler<T>
{
void Execute(T message);
}
I wrote a simple "Resolver" class:
public static class HandlerRegistry
{
private static readonly Dictionary<string, Type> _handlers = new Dictionary<string, Type>();
public static void Register<T, T2>() where T2: IMessageHandler<T>
{
_handlers.Add(typeof(T).FullName, typeof(T2));
}
public static IMessageHandler<T> Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler<T>) Activator.CreateInstance(type);
}
}
In this implementation everything is OK, but one part - the cast to IMessageHandler. When I'm trying to use this with a collection of messages this is what happens: the compiler doesn't know at compile time what actual messages are going to be in the collection - it just assumes that they are all subclasses of Message, so it's trying to cast IMessageHandler<ConcreteMessage> to IMessageHandler<Message> and obviously I'm getting an exception with invalid cast. In this case probably contravariance would help, but I'm not able to declare the parameter as out because I have the message in the Execute method parameters.
Does anyone know an elegant solution to this problem? I know I can make it "more runtime" - instead of using generics just declare
void Execute(Message m) and in each and every handler start with trying to cast to the type that I'm expecting, but as someone said somewhere - each and every cast that you write undermines the whole point of using a type system.
Option 1
If you do not care using reflection. You can add a Execute method to your HandlerRegistry instead of returning the handler back to the caller:
public static void Execute<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
var handler = Activator.CreateInstance(type);
type.GetMethod("Execute", new[] { parameters.GetType() })
.Invoke(handler, new object[] { parameters });
}
Option 2
If you do not care that one message handler can only subscribe to one message. We can take advantage of the Explicit Interface Implementation feature of C#:
// NOTE: This interface is not generic
public interface IMessageHandler
{
void Execute(object message);
}
public abstract class MessageHandler<T> : IMessageHandler
{
public abstract void Execute(T message);
// NOTE: Here we explicitly implement the IMessageHandler
void IMessageHandler.Execute(object message)
{
Execute((T)message);
}
}
Now your resolve method can change to:
public static IMessageHandler Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler)Activator.CreateInstance(type);
}
By the way, personally I would prefer to pass in a Type instead of the message instance.
Then make your handlers inherit from the generic abstract MessageHandler<T> instead of implementing IMessageHandler:
public class HandlerA : MessageHandler<MessageA>
{
public override void Execute(MessageA message)
{
Console.WriteLine("Message A");
}
}
public class HandlerB : MessageHandler<MessageB>
{
public override void Execute(MessageB message)
{
Console.WriteLine("Message B");
}
}
How about this for a message router:
class Tester
{
public void Go()
{
var a = new MessageA();
var b = new MessageB();
var c = new MessageC();
var router = new MessageRouter();
router.RegisterHandler(new HandlerA());
router.RegisterHandler(new HandlerB());
router.Route(a);
router.Route(b);
router.Route(c);
}
}
class MessageRouter
{
Dictionary<Type, dynamic> m_handlers = new Dictionary<Type,dynamic>();
public void RegisterHandler<T>(IMessageHandler<T> handler)
{
m_handlers.Add(typeof(T), handler);
}
public void Route(dynamic message)
{
var messageType = message.GetType();
if (m_handlers.ContainsKey(messageType))
{
m_handlers[messageType].Handle(message);
}
else
{
foreach (var pair in m_handlers)
{
if(pair.Key.IsAssignableFrom(messageType))
{
pair.Value.Handle(message);
}
}
}
}
}
class MessageA
{
public virtual string A { get { return "A"; } }
}
class MessageB
{
public string B { get { return "B"; } }
}
class MessageC :MessageA
{
public override string A { get { return "C"; } }
}
interface IMessageHandler<T>
{
void Handle(T message);
}
class HandlerA : IMessageHandler<MessageA>
{
public void Handle(MessageA message)
{
Console.WriteLine(message.A);
}
}
class HandlerB : IMessageHandler<MessageB>
{
public void Handle(MessageB message)
{
Console.WriteLine(message.B);
}
}
How about taking a slightly different approach: Instead of registering the type of a handler, why not register the actual handler instance which will process the message? This gives you much greater flexibility in instantiation of the handler, and removes any type ambiguities.
The idea is to be able to do this:
// have several handler classes
class FooMessageHandler : IMessageHandler<Foo>
{ }
class BarMessageHandler : IMessageHandler<Bar>
{ }
// have them instantiated - allows you to pass much more context
// than Activator.CreateInstance is able to do
var fooMessageHandler = new FooMessageHandler(various params);
var barMessageHandler = new BarMessageHandler(various params);
// register actual instances
HandlerRegistry.Register<Foo>(fooMessageHandler);
HandlerRegistry.Register<Bar>(barMessageHandler);
// handler registry will simply dispatch the message to
// one of the handlers
HandlerRegistry.Dispatch(someFooMessage);
Not only that, but the approach allows you to register multiple handlers for each message type:
// these will all get called when a Foo message is received
HandlerRegistry.Register<Foo>(fooMessageHandler);
HandlerRegistry.Register<Foo>(someOtherFooHandler);
HandlerRegistry.Register<Foo>(yetAnotherFooHandler);
What if you inherit all you messages from common abstract MessageBase and instead of making message handler interface IMessageHandler<T> generic, put constraint on Execute method itself?
Namely void Execute<T>(T message) where T : MessageBase.
This way you get the desired functionality and your message handler resolver, HandlerRegistry, needs only a minor tweak. Just change return type & constraint from IMessageHandler<T> to IMessageHandler.
Below are slightly modified MessageBase, IMessageHandler and HandlerRegistry.
(Related dotnetfiddle here https://dotnetfiddle.net/e6M1UA)
// Message
public abstract class MessageBase
{
public virtual void Action() // ...for examples sake
{
Console.WriteLine(GetType().Name);
}
}
// Message handler
public interface IMessageHandler
{
void Execute<T>(T message) where T : MessageBase;
}
// Resolver
public static class HandlerRegistry
{
private static readonly Dictionary<string, Type> Handlers =
new Dictionary<string, Type>();
public static void Register<T, T2>() where T2 : IMessageHandler
{
Handlers.Add(typeof(T).FullName, typeof(T2));
}
public static IMessageHandler Resolve<T>(T parameters)
{
var type = Handlers[parameters.GetType().FullName];
return (IMessageHandler)Activator.CreateInstance(type);
}
}
Now, if you test it using e.g. following implementations
public class Message1 : MessageBase
{}
public class Message2 : MessageBase
{
public override void Action()
{
Console.Write(#"Overriding ");
base.Action();
}
}
public class Message1Handler : IMessageHandler
{
public void Execute<T>(T message) where T : MessageBase
{
Console.Write(#"MessageHandler1 > ");
message.Action();
}
}
public class Message2Handler : IMessageHandler
{
public void Execute<T>(T message) where T : MessageBase
{
Console.Write(#"MessageHandler2 > ");
message.Action();
Console.WriteLine(#"...and then some");
}
}
With this block of code
HandlerRegistry.Register<Message1, Message1Handler>();
HandlerRegistry.Register<Message2, Message2Handler>();
var messages = new List<MessageBase>()
{
new Message1(),
new Message2()
};
foreach (var message in messages)
{
var handler = HandlerRegistry.Resolve(message);
handler.Execute(message);
}
You'll end up with console log
MessageHandler1 > Message1
MessageHandler2 > Overriding Message2
...and then some

How pass delegate to a method, where delegates are non static?

I'm just beginning understanding delegates, I have a class that implemens IDisposable:
public class MyClass : IDisposable
{
public delegate int DoSomething();
public int Zero() {return 0;}
public int One() {return 1;}
public void Dispose()
{
// Cleanup
}
}
A method (defined in an another class) that is using MyClass:
public class AnotherCLass
{
public static void UseMyClass(MyClass.DoSomething func)
{
using (var mc = new MyClass())
{
// Call the delegate function
mc.func(); // <-------- this is what i should actually call
}
}
}
The actual question: how pass the Zero() function to UseMyClass method? Do I have to create an instance of MyClass (I would like to avoid this...)?
public static void main(string[] args)
{
// Call AnotherClass method, by passing Zero()
// or One() but without instatiate MyCLass
AnotherClass.UseMyClass(??????????);
}
Is your intent that the instance is provided by the caller of the delegate, and not the creator of the delegate? C# does support such an unbound delegate, it's called an open delegate, and the instance becomes a parameter.
You have to use Delegate.CreateDelegate to create an open delegate, something like this:
public class MyClass : IDisposable
{
public delegate int DoSomething();
public int Zero() {return 0;}
public int One() {return 1;}
public void Dispose()
{
// Cleanup
}
}
public class AnotherCLass
{
public static void UseMyClass(Converter<MyClass,int> func)
{
using (var mc = new MyClass())
{
// Call the delegate function
func(mc);
}
}
}
AnotherClass.UseMyClass(
(Converter<MyClass, int>)Delegate.CreateDelegate(
typeof(Converter<MyClass, int>),
typeof(MyClass).GetMethod("One")
)
);
Of course, you can do it much more easily with a shim:
AnotherClass.UseMyClass( mc => mc.One() ); // C# 3 or later
AnotherClass.UseMyClass( delegate(MyClass mc) { return mc.One(); } ); // C# 2
Because it's an instance method, if you want to call it, you need an instance. That's simply how the CLR works. However, there are two options you could go with:
Make the member functions static. If they're as simple as returning a static value, there's no reason for them to be instance methods. However, if you do actually require instance data...
Use a singleton instance. This way you don't need to create a new instance every time you want to call your static method.
You can do the latter like this:
public class MyClass
{
private static MyClass singletonInstance;
public static MyClass SingletonInstance
{
get
{
if (singletonInstance == null)
{
singletonInstance = new MyClass();
}
return singletonInstance;
}
}
// the rest of your class implementation
}
Then, you can call your static method like so:
AnotherClass.UseMyClass(MyClass.SingletonInstance.Zero);
Cant be done without instantiation. Heres how you can do it:
public static void main(string[] args)
{
// Call AnotherClass method, by passing Zero()
// or One() but without instatiate MyCLass
AnotherClass.UseMyClass((new MyClass()).Zero);
}

Co/Contra-Variance with input and output

I have an issue with co/contra-variance. I understand you can't have both input and output. So here is a simple example:
public interface A<T>
{
T Object {get;set;}
}
public interface B
{
// Some stuff
}
public class BImplementor : B
{ }
public class Implementor : A<BImplementor> {}
Suppose you have these classes and I'm wanting to write a method like this
public void Command(B obj)
{
var a = (A<B>)Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
a.Object = obj;
}
I'm using Unity to resolve a A of the specifc implementor of B (specifically Implementor), but all I know about it is that it is an A<B>. I don't know of a way to do this directly and I don't think it is actually possible, but does anyone know of a workaround to simulate what I'm trying to do.
As you said, you cannot have both input and output, so let's change A<T> to A<in T> so Command can assign obj to the Object property:
public interface A<in T>
{
void SetObject(T obj);
}
public interface B { }
public class BImplementor : B { }
public class Implementor : A<BImplementor>
{
public void SetObject(BImplementor t) { ... }
}
The Command method essentially does this:
public void Command(B obj)
{
A<B> a = (A<B>)new Implementor();
a.SetObject(obj);
}
But this cast can never succeed, because A<B>.SetObject must accept any B as input, while Implementor.SetObject accepts only BImplementor objects as input!
Since you now that you'll only ever pass a BImplementor to A<B>.SetObject, you can work around the problem using reflection.
Workaround 1:
public void Command1(B obj)
{
object a = Unity.Resolve(typeof(A<>).MakeGenericType(obj.GetType());
a.GetType().GetMethod("SetObject").Invoke(a, new object[] { obj });
}
Workaround 2:
public void Command(B obj)
{
this.GetType()
.GetMethod("Command2")
.MakeGenericMethod(obj.GetType())
.Invoke(this, new object[] { obj });
}
public void Command2<T>(T obj) where T : B
{
A<T> a = Unity.Resolve<A<T>>();
a.SetObject(obj);
}

Categories