Pass object into method without adding argument to method? - c#

I have a simple interface called IEvent and it just contains this one method:
void Execute();
I have several derived classes from this interface and one of them needs access to an object that the caller of the method owns. The object is used in this fashion:
using (MyObject object = new MyObject(this.MessageService)
{
foreach (IEvent myEvent in eventList)
{
myEvent.Execute(); // <--- I need to pass object without adding argument here if possible?
}
}
I would add the object as a field in the derived class that needs access to it, but by the time I get to this part of the code, the IEvent objects are already constructed and running on a background thread. Currently, the only way I can think of is to add a setter in the IEvent interface for this object, but then I am exposing a field that most derived classes won't care about and doesn't seem like a clean solution.
I would add it as an argument to Execute(), but the problem is that the object belongs to an assembly that the assembly that contains IEvent doesn't know about (and don't want it to know about) and again 99% of the events don't care about this object anyway. Is there a better way to accomplish what I am trying to do here?

"If a class that implements IEvent does not/can not implement all the methods specified by IEvent the same way as they are declared in IEvent, that class should not implement IEvent in the first place." - Sweeper
So there's probably something wrong with your design of the whole program. I think you better revise your design a little bit and change some relationships between the classes and interfaces.
If you don't want to do that, there is another (not recommended) way to solve this problem.
Suppose your method caller is of type MethodCaller. You just change the declaration of Execute in the interface to this:
void Execute(MethodCaller obj = null);
And all the classes that implement IEvent can ignore the parameter except the class you mentioned in your question.

I'm going to piggyback on Jon Skeet's amazing knowledge of C#, .NET, CLR, IL and everything that surrounds any of those topics. You can't get to the instance of the calling object and especially the local varaible in the calling method. You can get its type, you can get the calling method through StackTrace, for example (StackTrace.GetFrames()), but none of those are going to do you any good in this situation. What you're trying to accomplish would require some heavy dive into the debugging API. As far as walking the stack, here's a quick sample I created to try see if I can figure something out for you (I made assumptions in regards to how your program is structured... obviously it's not a one to one sample):
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace SampleApp
{
class Program
{
static void Main(string[] args)
{
var eventList = new List<IEvent> { new SomeClass() };
using (MyObject obj = new MyObject(new MessageService()))
{
foreach (IEvent myEvent in eventList)
{
myEvent.Execute();
}
}
}
}
public interface IEvent
{
void Execute();
}
public class SomeClass : IEvent
{
public void Execute()
{
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingMethod = stackFrames[1].GetMethod();
var callingType = callingMethod.DeclaringType;
}
}
public class MyObject : IDisposable
{
public MessageService Service { get; }
public MyObject(MessageService service)
{
Service = service;
}
public void Dispose()
{
Service.Stop();
}
}
public class MessageService
{
public void Start() { }
public void Stop() { }
}
}
I like your question, because it presents an interesting and an unusual situation, but I'm afraid that you won't be able to accomplish your task without going outside of conventional routines that C# has in its arsenal. You may be able to pull something off with unmanaged code, but that's a different topic altogether.
However, aside from it being an interesting question... look at what you're trying to do. You have MyObject, which obviously implements IDisposable and will call Dispose() at the end of that using statement, and you're trying to grab its reference from a different assembly. I don't think this is a good idea.
I suggest revisiting your design and make use of things such as an optional parameter. May not be the "perfect" solution for your situation, as you'll pass it to every Execute in that foreach loop, but it's better than jumping through a thousand fiery hoops of debug API's.

Related

How to get/set a property of an interface that is not always implemented

What is a good (object oriented) way of setting a property of a class which implements an interface, when that property doesn't always exist in all classes that implement that same interface?
e.g.
Let's say I have an interface
public interface IDataRepository {
public DataStructure GetData(); // DataStructure is an arbitrary class, doesn't matter for this example
}
Now I also have two classes that inherit from this
public class DatabaseRepository : IDataRepository {
public DataStructure GetData()
{
// get data from database
}
}
and
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; }
public DataStructure GetData() {
// get data from files
}
}
Now my client method doesn't necessarily know what the repository is but here's what I want to do...
private DataStructure ReadData(IDataRepository repository)
{
repository.WorkingFolder = #"C:\Data"; // What is the best way of doing this?
return repository.GetData();
}
obviously the above code won't work and I could do...
if (repository is FileRepository) {
((FileRepository)repository).WorkingFolder = #"C:\Data";
}
or add WorkingFolder as a property of the interface (and therefore all the classes that implement it) even though in most cases it's irrelevant.
but both of these (esp. the first one) seem very inelegant and not very object oriented. What is the oop way of doing this kind of thing?
Edit
The obvious question is if the method doesn't know what repository is, how can it know the correct value for WorkingFolder... But the above is an over-simplification of what I'm trying to do, so let's just say it can find out...
Apparently your ReadData method can't actually accept any type of repository. It is only able to handle a FileRepository. That's what it expects, and that's what it needs to do its job. Given that, that's what it should actually accept as its parameter, rather than an interface that doesn't actually provide a contract that is sufficient for it to do its job.
The entire point of having an interface is so that anyone using that interface can use it without caring what the implementation is. So if you do want to use the interface you need to include enough information in the interface's definition such that it provides every operation that anyone using the interface needs, otherwise you're better off just not using it at all (at least for that specific operation).
As for the specific example given, you should probably just be providing an already configured repository, that has whatever values it needs in order to allow this method to do its work, as a parameter. It doesn't make sense for a method that's reading a value from an arbitrary repository to be configuring that repository at all. That is, if it really is reading something from an arbitrary repository.
As others have said in the comments, you should initialise these properties in the constructor. This is where you know what type you're creating, so you also know what arguments its constructor requires / can set those there.
Once you've initialised the object, you can just pass it around / have anything using that class operate against its interface.
Example:
public void Main(string[] args)
{
var myRepo = new FileRepository(args[0]); //Here's where we set the working directory
var myThing = new Thing();
var data = myThing.ReadData(myRepo);// of course, the current implementation means you could just call `myRepo.GetData()` directly, since ReadData just passes out the same response; but presumably that method adds some additional value..
Console.WriteLine(data.ToString());
}
Supporting Code
public class DatabaseRepository : IDataRepository {
DbConnection connection; //you may want a connection string or something else; going with this type just to illustrate that this constructor uses a different type to the FileRepo's
public DatabaseRepository(DbConnection connection)
{
this.connection = connection;
}
public DataStructure GetData()
{
// get data from database
}
}
public class FileRepository : IDataRepository {
public string WorkingFolder { get; set; } //Do you need set? Generally best to keep it constant after initialisation unless there's good reason to change it
public FileRepository (string workingFolder)
{
this.WorkingFolder = workingFolder;
}
public DataStructure GetData() {
// get data from files
}
}
How do I call the code that creates the class
i.e. maybe you've implemented a really basic factory pattern like so, and want to know how to provide arguments:
public class DataRepositoryFactory
{
Type baseType = typeof(IDataRepository);
IDictionary<string, Type> typeMap = new Dictionary<string, Type>() {
{"File", typeof(FileRepository) }
,{"Db", typeof(DatabaseRepository) }
}
public void RegisterType(string typeName, Type type)
{
if (!baseType.IsAssignableFrom(type)) throw new ArgumentException(nameof(type));
typeMap.Add(typeName, type);
}
public IDataRepository GetDataRepository(string typeName)
{
return (IDataRepository)Activator.CreateInstance(typeMap[typeName]);
}
}
(For a more complex example of a factory, see https://web.archive.org/web/20140414013728/http://tranxcoder.wordpress.com/2008/07/11/a-generic-factory-in-c).
I.e. in this scenario, when you call the factory you know what type you want, but you're only giving it a string to name/identify that class. You could add a params object[] args to your GetDataRepository method, allowing you to call it like so:
var myRepo = myDataRepositoryFactory.GetDataRepository("File", "c:\somewhere\something.dat");
That's a good approach / is actually what's used on the linked example above. However, it means that your call to this code differs for different types; since if we use variables instead of hardcoded values as in the above example we can't simply do the below, since myRepoType could be set to "Db", whilst "myFilePath" would be a string:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myFilePath);
That's fixable by calling:
var myRepo = myDataRepositoryFactory.GetDataRepository(myRepoType, myArgs);
i.e. where myArgs is an object[], giving all of the values required in the desired order to initialise the type. The piece to populate object[] with the required values could then take place at the same point at which you decided you wanted the type to be a file repo vs database repo. However, this approach isn't that clean / casting to and from objects stops you from getting help from the compiler.
So how do I improve things?
There are a few options. One is to replace the need to use object[] by instead creating a type to hold your arguments. e.g.
public interface IDataRepositoryConfiguration
{
//nothing required; this is just so we've got a common base class
}
public class FileRepositoryConfiguration: IDataRepositoryConfiguration
{
public string WorkingFolder {get;set;}
}
public class FileRepository : IDataRepository {
public FileRepository (IDataRepositoryConfiguration configuration)
{
var config = configuration as FileRepositoryConfiguration;
if (config == null) throw new ArgumentException(nameof(configuration)); //improve by having different errors for null config vs config of unsupported type
this.WorkingFolder = config.WorkingFolder;
}
//...
}
This still has some issues; i.e. we may pass a DatabaseRepositoryConfiguration as our IRepositoryConfiguration when creating a FileRepository, in which case we'd get the AgumentNullException at runtime; but this does avoid issues should parameters change order, and makes it less of a headache to code / debug.
Could it be further improved?
Dependency Injection offers one solution. This could be used along the lines of the code below (i.e. you create instances of each of your classes, providing the required arguments, and give each instance a name, so that you can later fetch that instantiation. Exactly what that code looks like would depend on the dependency injection library you used:
//setting up your repositories
var container = new Container();
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.For<IDataRepository>().Add(new FileRepository("\\server\share\customers")).Named("customers");
config.For<IDataRepository>().Add(new FileRepository("\\server\share\invoices")).Named("invoices");
config.For<IDataRepository>().Add(new DatabaseRepository(new DbConnection(configurationString))).Named("persist");
config.For<IDataRepository>().Use("persist"); // Optionally set a default
config.Populate(services);
});
//then later when you need to use it...
public DataStructure ImportCustomers(IContainer container)
{
var customerRepo = container.GetInstance<IDataRepository>("customers");
return customerRepo.GetData();
}
I'm sure there are many other approaches, and exactly what approach to use depends on how your program will operate. Hopefully the above is enough to get you past your current problem; but if you find you're still struggling please post a new question with more detail / saying where you're still having issues having considered these points.
If possible, I'd just put the value for that property in the constructor or create a subinterface, like others suggested.
If it's not possible, C# 7.X (don't remember the exact minor version) has a nice code structure for conditional casting:
IDataRepository repo = new FileRepository();
if (repo is FileRepository fileRepo)
{
fileRepo.WorkingFolder = "some dir";
}
However in your case, you should probably rethink your architecture and always pass (or even better always create) a repository object which is ready to be used.
a) Put it into the Inferface definitions. Deal with any "NotImplemented" Exceptions. You always have to expect those with Interfaces anyway.
For example, IEnumerable has a Reset() function. But in most cases it is not implemented. It is not even supposed to be implemented in most cases. Afaik it is only there for Backwards Compatabilty with some old COM stuff.
b) make a sub-interface just for the property
c) Verify the Interface is properly implemented via is checks (throw exceptions thows if nessesary, like Array.Sort will throw a InvalidOperation one), generic constraints, proper argument types and the like.

Delegate example what's the point

Like many other posts I've found on SO, I'm trying to get my head around delegates. Hopefully this example is not classed a duplicate because I am asking a specific question about a particular example.
public delegate void HelloFunctionDelegate(string message);
public class Delegate
{
static void Main()
{
HelloFunctionDelegate del = new HelloFunctionDelegate(GoodNight); // delegate will point to the GoodNight method
del("Hello"); // invoke the delegate
}
public static void GoodMorning(string strMessage)
{
Console.WriteLine(strMessage + " and good morning!");
Console.ReadKey();
}
public static void GoodNight(string strMessage)
{
Console.WriteLine(strMessage + " and good night!");
Console.ReadKey();
}
}
So in my example I understand that my delegate is a reference to any function that matches its signature and if I pass in GoodMorning I will see:
Hello and good morning!
and if I pass in GoodNight I will see: Hello and good night!
So its kind of like going through a middle man...
I don't understand is what's the point, why wouldn't I just directly call my GoodMorning / GoodNight methods as and when I need to use them?
Maybe there are better examples for when a delegate is useful, but in this example, why don't I just bypass the middle man?
Since you are asking concretely about this example and not in general: There is no point to doing that in this particular piece of code. It teaches you the mechanics of delegates but it does not teach you the point of using them.
In short, the point is that some piece of code can take a reference to a method without knowing what method it will actually receive. It can later call that delegate at will. That enables more abstractions than otherwise possible.
Consider you have the following delegate:
public delegate void CarEvent(Car car);
And then you have an implementation like the following:
public class Car : DataRecord
{
// An event to execute when the record is deleted
public CarEvent OnDelete { get; set; }
public void Delete()
{
this.DeleteRecord(); // Deletes this record from ex. the database
if (OnDelete)
{
OnDelete(this); // Executes the event
}
}
}
By using a delegate you can subscribe different methods to the OnDelete allowing you to do different things when the record is deleted.
Ex. you can make it so when the record is deleted it's deleted from a "ListView" that holds it.
public class CarList : ListView
{
public CarList()
: base()
{
foreach (var car in CarRecords.LoadCars())
{
var listViewItem = new ListViewItem(car);
car.OnDelete = this.DeleteCarFromList;
this.Items.Add(listViewItem);
}
}
private void DeleteCarFromList(Car deletedCar)
{
this.Items.Remove(deletedCar);
}
}
Of course the above is a rough example and there is a lot more things and different kind of situations where you can use delegates and most notably if you want to use them for events you should consider implementing them using the event keyword. - https://msdn.microsoft.com/en-us/library/awbftdfh.aspx
All in all you want to use delegates when the behavior may differ depending on the overall implementation of something. Like you might want to do one thing in one situation and something else in another situation, but they should both over-all do the same thing.
If you do not need different behaviors based on implementation then there's no need to use delegates. You'd always want to call a method directly if possible.
I hope this explained it okay.

How to find all the interfaces that extend a base interface on a given object?

I'm trying to create a crude/basic event Subscribe/Publish system just to experiment.
I created a base IEventListener interface, then a generic IEventListener<T> : IEventListener interface on top of that, which has a function OnEvent(T eventParam)
I then created a test class that implemented IEventListener<string> and IEventListener<int>
I thought that by passing it through the following:
Dictionary<Type, List<object>> _listenersByType = new Dictionary<Type, List<object>>();
foreach(Type interfaceType in listener.GetType().GetInterfaces())
{
if(interfaceType is IEventListener)
{
AddSubscriber(interfaceType.GetGenericTypeDefinition(), listener);
}
}
I could create a look up of Event Types to Objects to cast and publish the events to. However, when stepping through. I see it loop all the interfaces, I can see the type name is "IEventListener" but the condition is never true, and never adds my listener to the dictionary.
Pastebin of full code
Through means of which I am unsure (I poked around in the debugger), this fixes it:
foreach(Type interfaceType in listener.GetType().GetInterfaces())
{
if(interfaceType.GetInterfaces().Contains(typeof(IEventListener)))
{
AddSubscriber(interfaceType.GetGenericArguments()[0], listener);
}
}
But I cannot tell you why I have to check the interfaces, of the interface. Or why I have to call interfaceType.GetGenericArguments()[0] instead of interfaceType.GetGenericTypeDefinition().
Part of me feels like this code is bad and I've got a design issue here. I would never expect the solution to be so... Ugly.
You could just ask the object itself if it implemets interface. For exampl i have created fake class:
public class SListener<T> : IEventListener<T>
{
public void OnEvent(T eventParam)
{
}
}
and object of it
var s = new SListener<string>();
if i ask
bool t = (s is IEventListener);
it is true.
So your subscribe mthod could be like :
public void Subscribe(object listener)
{
if(listener is IEventListener)
{
AddSubscriber(interfaceType.GetGenericTypeDefinition(), listener);
}
}

Generic Interfaces and Type Parsing

I am trying to pass messages between several classes that communicate through interface. However, as I like to go as generic as possible, I ran into problems because the message type of incoming messages may be different from the outgoing type. I pasted some code to make it clearer.
The code below does not compile because the interface implementation passes a different type than the type of the blocking collection to which it is supposed to add incoming messages. I want to be able to send types potentially different from incoming types (incoming types obviously always match the type of the elements in the blocking collection). Can I somehow get around any sort of casting or parsing even if that means I need to redesign my interface or class?
I am still quite fresh when it comes to working with interfaces and struggled with recursions, stack overflow errors, and the like. So, if you have suggestions what I can improve design wise or just a quick fix then please help me to learn. Am very eager to understand how to implement a better pattern.
Thanks
public interface IClientMessaging
{
void MessagePassing<U>(U message);
}
public class InProcessMessaging<T> : IClientMessaging
{
private Dictionary<Type, List<IClientMessaging>> Subscriptions;
public BlockingCollection<T> MessageBuffer;
public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions)
{
//Setup Message Buffer
MessageBuffer = new BlockingCollection<T>();
//Subscribe
Type type = typeof(T);
if (subscriptions.Keys.Contains(type))
{
subscriptions[type].Add(this);
}
else
{
subscriptions.Add(type, new List<IClientMessaging>());
subscriptions[type].Add(this);
}
Subscriptions = subscriptions;
}
public void SendMessage<U>(U message)
{
//Send message to each subscribed Client
List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)];
foreach (IClientMessaging subscriber in typeSubscriptions)
{
subscriber.MessagePassing<U>(message);
}
}
public T ReceiveMessage()
{
return MessageBuffer.Take();
}
public bool ReceiveMessage(out T item)
{
return MessageBuffer.TryTake(out item);
}
//Interface Implementation
public void MessagePassing<U>(U message)
{
MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want
//to send messages of a different type than the receiving type]
}
}
I'm struggling to understand your goal here, but perhaps MessagePassing<U>(U message) should be MessagePassing(U message) and interface IClientMessaging should be interface IClientMessaging<U>.
Then InProcessMessaging<T, U> : IClientMessaging<U> - but I don't see why InProcessMessaging implements IClientMessaging AND manages subscriber lists of IClientMessaging. Seems to me that one class would manage the subscribers and another IS a subscriber (IClientMessaging).
You say U and T are different types. Well - are they related? Is one wrapper for the other? Sounds like maybe U is either a wrapper for T, a generic class itself that contains the T but adds extra info. In that case, void MessagePassing<T>(Wrapper<T> message);
UPDATES
Based on the comments so far ...
interface IClientMessage {}
interface IClientMessage<U> : IClientMessage { /* ... */ }
But rename those to:
interface IConsumer {} // (Or ISubscriber?)
interface IConsumer<TConsumed> : IConsumer{ /* ... */ }
and add:
interface IGenerator { }
interface IGenerator <TGenerated> : IGenerator {
event EventHandler<TGenerated> ItemGenerated;
}
Then:
class Manager
{
Dictionary<TConsumed, IConsumer> consumers = new ...
/* Code for attaching ItemGenerated event handlers to clients */
}
class MyClient : IGenerator<string>, IConsumer<Foo>, IConsumer<Bar>
{
event IGenerator<string>.ItemGenerated ...
void IConsumer<Foo>.Consume(...) ...
void IConsumer<Bar>.Consume(...) ...
}
Yes, this would use reflection to invoke IConsumer<TConsumed>.Consume(). Or you can leave off the generics and just use object as your types. Better yet, IClientMessage can have a Consume(object message) which in your implementation can ensure that object is a TConsumed before attempting to process it.
You could otherwise create direct client-to-client links through C# events, but you seem intent on a central dispatcher. It is the central dispatchers need to keep track of these different and unbounded number of types that is either going to require reflection OR be unaware of the types being passed (as described in the previous paragraph)
You should look at Reactive Extensions and the Observer pattern for ideas as well.
I removed my comments because it was getting too chatty.

Tracking instances with generics and supporting subclasses

I've defined the following generic class
public class ManagedClass<T> where T : ManagedClass<T>
{
static ManagedClass()
{
Manager = new ObjectManager<T>();
}
public static ObjectManager<T> Manager { get; protected set; }
public ManagedClass()
{
Manager.Add( (T)this );
}
}
The idea is that I can use it like so:
class Product : ManagedClass<Product> {}
Now I can do something to the 7th product created like so:
Product.Manager.GetById(7).DoSomething();
The problem comes in if i try to use a derived class:
class ExtendedProduct : Product {}
now ExtendedProduct.Manager has a list of 'Products', and if i want to use a new function that I have added to ExtendedProduct (DoSomethingElse), I have to cast the object I get back like so:
((ExtendedProduct)ExtendedProduct.Manager.GetById(7)).DoSomethingElse();
This is a bit ugly, and the whole point of using generics for this is to avoid casting. I suppose I could add a static constructor to the derived class to set Manager = new ObjectManager() and add a new Manager.addObject( this ) in the derived class constructor, but It seems like there should be some better way of doing this using generics. Any suggestions?
The problem is that ExtendedProduct.Manager is the same thing as Product.Manager; the manager object can't act differently depending on where it's accessed from.
A couple of possibilities I can think of:
Hide the typecast inside the GetById method by making it generic:
Product.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
Use one ObjectManager instance per subclass, connecting them privately if needed
Option 1 reminds me of NHibernate's ICriteria interface. It's effectively the same as a typecast, but a little harder to accidentally break.
Really what you're running into is a weakness with Generics. Once your class has resolved what type it's using for generics, you're somewhat restricted in what you can do.
Normally, I'd say Dependency Injection would be a savior here, but since the problematic method is static, that muddies up the waters.
I'd say the best thing is to have the ObjectManager class do the work for you:
static public class ObjectManager<T>
{
... the code that already exists in ObjectManager ...
static public U GetById<U>(long id)
{
object obj = GetById(id);
if (obj is U)
return (U)obj;
return default(U);
}
}
Then, in your code:
ExtendedProduct.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
It's not really tons more elegant than casting, but may be one of the only solutions using Generics.

Categories