Listen to object instantiation - c#

I have interface and some classes that implement this interface.
I want to listen for any object that will be instantiated and check if this object implements my interface.
My primary reason is to store all references to this kind of objects and simply call a method of interface to all objects.

As Kyle said in the comments the constructor of an abstract class would be the best choice. Or a factory that must be used for construction of those kind of objects.
But if this is not an option maybe the following approach is acceptable in your case.
If the "listener" is globally accessible (e.g. something static) you can add methods like Register(IYourInterface obj) and Unregister(IYourInterface obj) to it and ensure that every class that implements the interface will call these methods on construction / deconstruction. Not the cleanest way, but it will work as long as you maintain this behavior.
Example:
public static class Listener
{
private static List<IMyInterface> objects = new List<IMyInterface>();
public static void Register(IMyInterface obj)
{
if (!objects.Contains(obj))
objects.Add(obj);
}
public static void Unregister(IMyInterface obj)
{
if (objects.Contains(obj)
objects.Remove(obj);
}
public static void DoSomethingWithObjects()
{
foreach (IMyInterface obj in objects)
// do something ...
}
}
public class SomeTestClass : IMyInterface
{
public SomeTestClass()
{
Listener.Register(this);
}
}

There are a few ways to go about this.
Use a base abstract class
Easiest solution is to have a base class that everything inherits from. This kind of defeats the purpose of the interface, but this is the only way you can add this sort of code for creation. You could do something like:
public abstract class AbstractBaseClass
{
public AbstractBaseClass()
{
ObjectRegister.StoreReference(this);
}
public abstract void MethodToCall();
}
public class SubClass : AbstractBaseClass
{
public SubClass() : base() //Don't forget 'base()'!
{
//Your code here
}
public override void MethodToCall()
{
Console.WriteLine("Called in SubClass");
}
}
The abstract MethodToCall could also be virtual if you want to provide a default action, but if it's abstract the compiler will complain that you haven't implemented it in a similar way to interfaces.
Use a public static instantiating method
A bit more verbose, but can be seen in things like Unity. In this case, instead of doing x = new Y(), you have a public static method, perhaps a generic one, that creates the class for you, registers it, then returns that instance. Assuming your interface is called 'IRegisterable', you could have something like:
public static class ObjectRegister
{
//Note the 'where', which constrains T to be something that
//implements IRegisterable
public static T Instantiate<T>() where T:IRegisterable
{
T obj = new T();
StoreReference(obj);
return obj;
}
private static StoreReference(IRegisterable obj)
{
//Do your storing code here. This doesn't even need to be a method
//if your reference storing stuff only happens on object creation
}
}
//Elsewhere, where class 'Thing' implements IRegisterable
Thing x = ObjectRegister.Instantiate<Thing>();
//x is now registered. No need to do x = new Thing()
string y = ObjectRegister.Instantiate<string>();
//Error: string does not implement IRegisterable
Unfortunately, supplying constructor arguments this way isn't easy. You could just have an Init() method though which acts as a sort of fake constructor.

Related

How to enforce a derived type for a method that is implemented from abstract?

My abstract class has a method that is abstract like this:
public abstract void Run(BaseType baseType);
And now in my derived class which has to implement this function, i want it to only accept a specific derived type from BaseType
So it would have:
public override void Run(DerivedType derivedType){}
Is there any way to enforce this at all ?
Currently i have to do:
public override void Run(BaseType baseType) {
if(!(baseType is DerivedType)) {
// throw exception
}
}
It's not very strict with enforcing the type - i was wondering if there is a way to do so without the need to constantly add a type check ?
I've sometimes used this pattern:
public interface IHandler
{
void Run();
}
public abstract class BaseHandler<TObj> : IHandler
where TObj: BaseType
{
protected readonly TObj _obj {get;set;}
public BaseHandler(TObj obj)
{
this._obj = obj;
}
public abstract void Run();
}
public class DerivedHandler : BaseHandler<DerivedType>
{
public DerivedHandler(DerivedType obj) : base(obj)
{
}
public override void Run()
{
// do stuff with base._obj
}
}
public class HandlerService
{
public IHandler CreateHandler<TObj>(TObj obj)
{
// Depending on your DI container, you could resolve this automatically from the container
if (typeof(TObj) == typeof(DerivedType))
{
return new DerivedHandler(obj);
}
throw new NotImplementedException();
}
}
This allows you to define a specific "handler" for each derived type, and then access it through a common interface.
The idea is that you instantiate a specific handler for the object, and then methods like Run() operate on that object. You can then resolve a handler through the service.
I'll fill in some more info later when I have time.
You want the language to do something that it really shouldn't. You want a covariant argument, which violates the Liskov Substitution Principle: It makes the implementation of the abstract class not usable in every situation where the abstract base class is usable. This is the whole point of abstract base classes to begin with.
Although it could make sense to have a covariant return type (returning a more derived type then the abstract methods specifies) the language also prevents you to do that.

Subclassing and generics in C#

I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:
public class SuperT<T> : T
{
//the same set of properties
}
But the compiler says
Cannot derive from 'T' because it is a type parameter
EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)
One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.
If these classes all share a common base class or common interface you could write an extension method.
public static class ShapeExetnsionsExtLib
{
public static double Radius(this ShapeBase shape){
return /*calculate radious*/;
}
}
From comments
I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".
Yes they share common base classes but I cannot add anything new to them.
I don't think generics have anything to do with this, however inheritance is probably what you're looking for.
There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.
Is-A inheritance
Has-A inheritance
And to simply add a similar method to a bunch of third party objects, you'll use an extension method.
Is-A inheritance
Use a base class if you've got similar method implementations.
public abstract class BaseFoo {
public void Bar() {
// actual code
}
}
public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();
Use an Interface if you need to implement the same method on each class.
public interface IFoo {
void Bar();
}
public class Foo : IFoo {
public override void Bar(){
// bar implementation
}
}
var foo = new Foo();
foo.Bar();
Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.
Has-A inheritance
This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.
public class Foo {
private readonly ThirdPartyFoo _tpFoo;
void Foo(ThirdPartyFoo tpFoo) {
_tpFoo = tpFoo;
}
public void Bar(){
// now I can do something with _tpFoo;
_tpFoo.Bar();
}
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo
Lastly, if you just need to add a method to existing classes, then you create an extension method.
public static class ViewExtensions()
{
// this assumes your Image, Button, Label all inherit from View.
public static Whatever Radius(this View view) {
// do your radius work.
}
}
Just Use a base class:
public class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
And inherite from it:
public class A : Base
{
}
public class B : Base
{
}
In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.
(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)
// The sealed class within another library
public sealed ThirdPartyClass
{
public ThirdPartyClass(int i) { }
public int SomeProperty { get; set; }
public int SomeMethod(string val) { return 0; }
public static void SomeStaticMethod() { }
}
// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
private ThirdPartyClass _obj;
public BaseClass(int i) { _obj = new ThirdPartyClass(i); }
public int SomeProperty
{
get { return _obj.SomeProperty; }
set { _obj.SomeProperty = value; }
}
public int SomeMethod(string val) { return _obj.SomeMethod(val); }
public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}
// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{
}
First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?
Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.

Defining factory methods in interfaces or abstract superclasses of the product class

I have an abstract super class and subclasses inheriting from it.
Each subclass MySubclass shall have a public static MySubclass CreateFrom(ISomething something) factory method. The interface of its argument is the same for all subclasses, but the return type must of course always be the type of the respective subclass.
Can I somehow achieve this to have static factory methods following an interface or abstract superclass method definition without creating a separate static factory class for each single subclass?
If the ISomething is always of the same (or at least a common) type, you could make the CreateFrom method of the superclass generic and Invoke the constructor of the inherited class with the parameter. Just make sure all your inherited classes have that constructor (Not sure but I don't think there is a way to 'force' a constructor pattern).
public abstract class SuperClass
{
public static T CreateFrom(ISomething something)
{
return (T)Activator.CreateInstance(typeof(T), something);
}
}
public class InheritedClass : SuperClass
{
public InheritedClass(ISomething something)
{}
}
This way you can create instances by calling
SuperClass.CreateFrom<InheritedClass>(something);
Or you split the creation and initialization:
public abstract class SuperClass
{
protected abstract void Initialize(ISomething something);
public static T CreateFrom(ISomething something) where T : new()
{
T result = new T();
T.Initialize(something);
}
}
public class InheritedClass : SuperClass
{
public InheritedClass()
{}
protected override Initialize(ISomething something)
{}
}
You can´t define static members on interfaces as static members belong to a certain class. However I can´t imagine of a reason to use this. You should ask yourself why you need such a functionality. Does a sub-class really have to instantiate itself or can the same easily be done with another independent (factory-)class?
Just create one simple factory-class with a generic parameter that indicates what to create.
class Factory<T> where T: new()
{
T CreateFrom(ISomething param)
{
return new T();
}
}
Now you can simply call it like this:
var myFactory = new Factory<MyClass>();
myFactory.CreateFrom(mySomething);
I resorted to a different solution in similiar kind of requirement. In my superclass which happened to be an abstract one I required to create an instance of subclass to do something with it so I did the following trick:
public abstract class Element
{
protected virtual void copyFrom(Element other)
{
}
protected abstract Elememt newInstanceOfMyType();
public object clone()
{
var instance= newInstanceOfMyType();
instance.copyFrom(this);
return instance;
}
}
Now all my subclasses inheriting from Element class required to override newInstanceOfMyType method to give away instance of its type and then also override copyFrom method to produce a perfect clone. Now people might argue that why an abstract Clone method cant do the same job? Yes it can. But I required cloned instance of subclass as well as an empty instance(without copying anything from current) so I came up with this architecture.

Add an extra method in only one of the many subclasses of an abstract class

I have an abstract class but and 6 different implementations of it. Now for one of them I would like to add an extra public method but would not like to add it to the abstract class because the other 5 implementations don't need it.
Is there a way of implementing this? I am getting an error when I add this new method without it being in the abstract class.
Here is the code:
namespace Results.Parser
{
public abstract class Parser<T> where T: ReportItem
{
public abstract string GetNodeName();
public abstract IEnumerable<ReportItem> ParseXml(TextReader stream);
public abstract List<ReportItem> SumValueOfDuplicateRows(List<T> reportList);
public virtual bool MeetsCriteria(ReportItem reportItem)
{
return reportItem.Value.SafeConvertToDecimal() != 0;
}
}
}
public class ElementParser : Parser<ReportItem>
{
public override string GetNodeName()
{
return "Element";
}
public override List<ReportItem> SumRiskValueOfDuplicateRows(List<ReportItem> reportList)
{
// do something
}
public void SerializeXml(TextReader stream)
{
//new method which is not in abstract class
}
public override IEnumerable<ReportItem> ParseXml(TextReader stream)
{
//do something
}
}
namespace Results.Producer
{
public class RepositoryManager
{
private void GetResponse(TextReader stream)
{
var parser = new ElementParser();
parser.SerializeXml(stream);
}
}
I am getting an error when I add this new method without it being in the abstract class.
A superclass reference to a subclass instance can't access methods not defined in the super class. You will need to explicitly cast your reference to a subclass reference type to be able to access the extra method from the subclass.
Let A be the abstract class and let B be the class where you have an extra method called extra. Let a be a reference of type A to an instance of type B. To access the extra method in B, do this :
((B)a).extra();
That being said, if only one of the classes needs additional behavior that is different, you should consider using composition over inheritance. See this answer that explains the famous duck problem that is similar to the situtation you are in currently

Is generic constructor in non-generic class supported?

Is it not supported, is it supported but I have to do some tricks?
Example:
class Foo
{
public Foo<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
{
...
}
}
the generics are only used in constructor, there is no field/property depended on them, I use it (generics) to enforce the type correlation for f1 and f2.
Remark: I found the workaround -- static method Create, but anyway I am curious why I have problem with straightforward approach.
No, generic constructors aren't supported in either generic or non-generic classes. Likewise generic events, properties and finalizers aren't supported.
Just occasionally I agree it would be handy - but the syntax would look pretty awful. For example, suppose you had:
public class Foo<T> {}
public class Foo
{
public Foo<T>() {}
}
What would
new Foo<string>()
do? Call the generic constructor of the non-generic class, or the normal constructor of the generic class? You'd have to differentiate between them somehow, and it would be messy :(
Likewise, consider a generic constructor in a generic class:
public class Foo<TClass>
{
public Foo<TConstructor>() {}
}
How would you call the constructor? Hopefully we can all agree that:
new Foo<string><int>()
is pretty hideous...
So yes, semantically it would be occasionally useful - but the resulting ugliness counterbalances that, unfortunately.
Generic constructors are not supported, but you can get around this by simply defining a generic, static method that returns a new Foo:
class Foo
{
public static Foo CreateFromFuncs<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
{
...
}
}
which is used like this:
// create generic dependencies
var func1 = new Func<byte, string>(...);
var func2 = new Func<string, byte>(...);
// create nongeneric Foo from dependencies
Foo myFoo = Foo.CreateFromFuncs<byte, string>(func1, func2);
Here is an practical example about how you would like to have extra constructor type parameter, and the workaround.
I am going to introduce a simple RefCounted wrapper for IDisposable:
public class RefCounted<T> where T : IDisposable
{
public RefCounted(T value)
{
innerValue = value;
refCount = 1;
}
public void AddRef()
{
Interlocked.Increment(ref refCount);
}
public void Dispose()
{
if(InterlockedDecrement(ref refCount)<=0)
innerValue.Dispose();
}
private int refCount;
private readonly innerValue;
}
This seems to be fine. But sooner or later you would like to cast a RefCounted<Control> to RefCounted<Button> whilst keep both object reference counting, i.e. only when both instances being disposed to dispose the underlying object.
The best way is if you could write (like C++ people can do)
public RefCounted(RefCounted<U> other)
{
...whatever...
}
But C# does not allow this. So the solution is use some indirection.
private readonly Func<T> valueProvider;
private readonly Action disposer;
private RefCounted(Func<T> value_provider, Action disposer)
{
this.valueProvider = value_provider;
this.disposer = disposer;
}
public RefCounted(T value) : this(() => value, value.Dispose)
{
}
public RefCounted<U> Cast<U>() where U : T
{
AddRef();
return new RefCounted<U>(() => (U)(valueProvider()),this.Dispose);
}
public void Dispose(){
if(InterlockedDecrement(ref refCount)<=0)
disposer();
}
If your class have any fields that are of generic type, you have no choice but to put all those types to the class. However, if you just wanted to hide some type from the constructor, you will need to use the above trick - having a hidden constructor to put everything together, and define a normal generic function to call that constructor.

Categories