C# Use Generics to Call Overridden Method - c#

I think I am a bit mixed up at this point, but I can't seem to be able to solve this issue.
I have an Interface ILinkHandler<T> and 4 other handler classes (inheriting from that interface) that validate different structures of links. From that interface, I have a Task<List<T>> Validate() function that does the validation of links and returns a Task> of results. Depending on T, I return a different model on Validate() (I have 4 different models).
My console app does the following. It calls the Task<List<T>> Validate(); method of every link type and creates some logs after getting results (note that Validate() is async). Every log is a little bit different, since the model is different, so I overrode a method named WriteResults(ModelX results, string name) and from the ModelX type (see end of question, I posted 2 examples), I do some stuff different (not important on this scope I think, but I can provide details if necessary). This method is NOT async.
I wanted to use Generics and my Interface to create a method (ValidateModel<T>) that handles the right call to the overridden method WriteResults from the type of the model and calls the Validate() method from the interface.
The code below is that I did that worked, but the if part resembles what I currently have in my main and I want to avoid.
public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
Console.WriteLine($"Validating {name}");
var results = handler.Validate();
if (typeof(T) == typeof(InternalLinksModel))
{
WriteResults(results.Result as List<InternalLinksModel>, name);
}
else // continue with other models
}
Here is what I have in my main:
private static void Main(string[] args)
{
Console.WriteLine("Validating External_Links");
var resultsForExternalLinks = ExternalLinkHandler.Validate();
WriteResults(resultsForExternalLinks.Result, "External_Links");
Console.WriteLine("Validating Image_Links");
var resultsForImageLinks = ImageLinkHandler.Validate();
WriteResults(resultsForImageLinks.Result, "Image_Links");
// and so on
}
I want more something like this if possible, but this does not compile:
public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
Console.WriteLine($"Validating {name}");
var results = handler.Validate();
WriteResults<T>(results.Result as List<T>, name);
}
Here is the definition of WriteResults (note that since it's overridden, I have 4 methods with their signature changing in the type of the list):
private void WriteResults(List<InternalLinksModel> results, string filename) { // Logs results into folder to display in jenkins }
private void WriteResults(List<PdfLinksModel> results, string filename) { // Logs results into folder to display in jenkins }
// and so on
EDIT: Adding more code
Interface:
public interface ILinkHandler<T>
{
Task<List<T>> Validate();
}
Example of Handler Class inheriting the interface:
public class InternalLinkHandler : ILinkHandler<InternalLinksModel>
{
public List<InternalLinksModel> InternalLinks = new List<InternalLinksModel>();
public async Task<List<InternalLinksModel>> Validate()
{
// Here set up my tests, call tasks that modifies InternalLinks List and I await for its results
return InternalLinks
}
Main Class (named XmlLinkCheckerValidator) where my code runs currently (and it works):
public class XmlLinkCheckerValidator
{
// References to all modes
public ExternalLinkHandler ExternalLinkHandler => new ExternalLinkHandler();
public ImageLinkHandler ImageLinkHandler => new ImageLinkHandler();
public InternalLinkHandler InternalLinkHandler => new InternalLinkHandler();
public PdfLinkHandler PdfLinkHandler => new PdfLinkHandler();
public void ValidateIPack()
{
InitialSetup();
Console.WriteLine("Validating External_Links");
var resultsForExternalLinks = ExternalLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForExternalLinks.Result, "External_Links");
Console.WriteLine("Validating Image_Links");
var resultsForImageLinks = ImageLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForImageLinks.Result, "Image_Links");
Console.WriteLine("Validating Internal_Links");
var resultsForInternalLinks = InternalLinkHandler.Validate();
WriteResultsForIPacksInCsv(resultsForInternalLinks.Result, "Internal_Links");
// Console.WriteLine("Validating Pdf Links");
// var results = XmlLinkExtractorFromIPacks.PdfLinkHandler.Validate();
// WriteResultsForIPacks(results, "Pdf Links");
}
private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<ExternalLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<ImageLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<PdfLinksModel> results, string filename) { logging results }
private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }

I finally refactored all my code and it looks much clear. As I said, in the beginning, I think I got a bit mixed up and it all started from one bad design decision I took.
In short, I added a new method, WriteResults(string filename). Doing so, I implemented the method and removed the overridden method (WriteResultsForIPacksInCsv(List<WhateverModelIHad> results, string filename)) from my "Main" class. From that, I changed the Validate method signature in the interface to Task<List<PossibleResults>> Validate() and since every model has that in common, I removed the generic in the interface. I can now call my handlers the following way:
public void Validate(ILinkHandler handler, string filename)
{
Console.WriteLine($"Validating {filename}");
var results = handler.Validate();
SetUpResultsStatistics(results.Result, $"{filename}_Statistics");
handler.WriteResults(filename);
}
I created a function named void SetUpResultsStatistics(List<PossibleResults> results, string filename) which gives statistics of results and it is common to all handlers (thus, to avoid duplication I put it there).
Code is now much clearer and it now does not use any generics nor overridden method. I, however, am still curious as to how should I handle a case like that and will try to formulate it in another question with a much simpler example.
Thank you all for your comments, really appreciated!

Related

C# attributes and methods

Good day, everyone,
recently I've come across the Discord.NET Api and was in love with the way Commands were handled. Essentially, to add a new Command that is executed when you write !ping, you can do this:
[Command("ping")]
public async Task Ping()
{
//some logic here
}
And I really liked the easy nature of integrating new commands in an already existing API. So I wanted to recreate what was going on. In the beginning I was absolutely confused by the introduction of metaprogramming, but now feel a little more comfortable, so I tried to start, and designed an Attribute that was only assignable to methods:
[AttributeUsage(AttributeTargets.Method)]
public class Command : Attribute
{
public string Name { get; set; }
public Command(string name)
{
Name = name;
}
public Command()
{
Name = string.Empty;
}
}
Basic idea then is, that when my Console gets a command, I can run a method that has the command attribute and the name of what was entered in the console. So when I enter "ping" in the console, the below method is going to be executed.
[Command("ping")]
public void Ping()
{
//do sth
}
Now to the complicated part. How do I find and especially run that method? That's where I'm stuck right now. I really don't find anything helpful about that question on the .Net documentary or here on stackoverflow. Here is my attempt anyway:
public void Handle(string command)
{
var methods = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes<Command>().Count() > 0
select t;
//run method where command.name = ping
}
The idea behind that being, to iterate through all available methods in the assembly, and then putting those into a List of some kind and then executing the method that has the command.name of what was passed in as an argument to the Handle function. When I get that to work, I of course will initilaize the methods list in the constructor of that class and not everytime call it when Handle is called, but for simplicity in my question I formulated my question independent of that, to have my example minimal. The question now is, how do I iterate through all methods in my assembly, and save those with the command attribute into a collection, and how do I run a method that has a certain value for the command.Name property?
I'am kind of new to that whole reflection stuff, so if I did something else stupid or you have general tips on that topic please let me know!!
Thanks in advance!!
I have written a small demo application that should help you to complete your logic. Overall, of course, it still has room for improvement, but it works:
using System;
using System.Linq;
using System.Reflection;
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
string command = Console.ReadLine().Trim();
LogicProvider provider = new LogicProvider();
MethodInfo method = provider.GetType().GetMethods().FirstOrDefault((item) => item.GetCustomAttribute<CommandAttribute>().Identifier == command);
method?.Invoke(provider, null);
}
}
public class LogicProvider
{
[Command("DemoCommand")]
public void MyMethod()
{
Console.WriteLine("Here");
}
}
public class CommandAttribute : Attribute
{
public CommandAttribute(string identifier)
{
this.Identifier = identifier;
}
public string Identifier { get; } = null;
}
}
If DemoCommand is entered in the console, then a search is made in the LogicProvider for a matching method. If there is a match, it is executed.
The whole thing also works with methods that have parameters. In the case of method?.Invoke(), this can then be specified.

General design guidance c#; finding im unnecessarily passing objects between methods

Sorry its a bit vague perhaps but its been bugging me for weeks. I find each project I tackle I end up making what I think is a design mistake and am pretty sure theres a bettwe way.
When defining a class thats serialized from an event source like a sinple json doc definition. Lets call it keys class with various defined integers, bools and strings. i have multiple methods that make use of this and i find that i constantly need to paas this class as an object by means of an overload. So method a calls methods b, method b doesnt need these objects but it calls method c which does... In doing this bad practice im passing these 'keys' objects to method b for the sole purpose of method c accessibility.
Im probably missing one major OOP fundamental :) any guidance or reading would be appreciated as im googled out!!
public class Keys
{
public child Detail { get; set; }
}
public class child
{
public string instance { get; set; }
}
//my main entry point
public void FunctionHandler(Keys input, ILambdaContext context)
{
methodA(input)
}
static void methodA(Keys input)
{
//some-other logic or test that doesn't need Keys object/class if (foo==bar) {proceed=true;}
string foo = methodB(input)
}
static string methodB(Keys input)
{
//here i need Keys do do stuff and I return a string in this example
}
What you do is not necessarily bad or wrong. Remember that in C# what you actually pass are references, not objects proper, so the overhead of parameter passing is really small.
The main downside of long call chains is that the program logic is perhaps more complicated than it needs to be, with the usual maintainability issues.
Sometimes you can use the C# type system to let the compiler or the run time choose the proper function.
The compiler is employed when you overload method() for two different types instead of defining methodA() and methodB(). But they are distinguished by the parameter type, so you need different Key types which may be (but don't have to be) related:
public class KeyA {/*...*/}
public class KeyB {/*...*/}
void method(KeyA kA) { /* do something with kA */ }
void method(KeyB kB) { /* do something with kB */ }
This is of limited benefit; that the functions have the same name is just syntactic sugar which makes it clear that they serve the same purpose.
The other, perhaps more elegant and versatile technique is to create an inheritance hierarchy of Keys which each "know" what a method should do.
You'll need a base class with a virtual method which will be overridden by the inheriting classes. Often the base is an interface just declaring that there is some method(), and the various implementing types implement a method() which suits them. Here is a somewhat lengthy example which uses a virtual Output() method so that we see something on the Console.
It's noteworthy that each Key calls a method of an OutputterI, passing itself to it as a parameter; the outputter class then in turn calls back a method of the calling object. That's called "Double Dispatch" and combines run-time polymorphism with compile-time function overloading. At compile time the object and it's concrete type are not known; in fact, they can be implemented later (e.g. by inventing another Key). But each object knows what to do when its callback function (here: GetData()) is called.
using System;
using System.Collections.Generic;
namespace DoubleDispatch
{
interface KeyI
{ // They actually delegate that to an outputter
void Output();
}
interface OutputterI
{
void Output(KeyA kA);
void Output(KeyExtra kE);
void Output(KeyI k); // whatever this does.
}
class KeyBase: KeyI
{
protected OutputterI o;
public KeyBase(OutputterI oArg) { o = oArg; }
// This will call Output(KeyI))
public virtual void Output() { o.Output(this); }
}
class KeyA : KeyBase
{
public KeyA(OutputterI oArg) : base(oArg) { }
public string GetAData() { return "KeyA Data"; }
// This will compile to call Output(KeyA kA) because
// we pass this which is known here to be of type KeyA
public override void Output() { o.Output(this); }
}
class KeyExtra : KeyBase
{
public string GetEData() { return "KeyB Data"; }
public KeyExtra(OutputterI oArg) : base(oArg) { }
/** Some extra data which needs to be handled during output. */
public string GetExtraInfo() { return "KeyB Extra Data"; }
// This will, as is desired,
// compile to call o.Output(KeyExtra)
public override void Output() { o.Output(this); }
}
class KeyConsolePrinter : OutputterI
{
// Note: No way to print KeyBase.
public void Output(KeyA kA) { Console.WriteLine(kA.GetAData()); }
public void Output(KeyExtra kE)
{
Console.Write(kE.GetEData() + ", ");
Console.WriteLine(kE.GetExtraInfo());
}
// default method for other KeyI
public void Output(KeyI otherKey) { Console.WriteLine("Got an unknown key type"); }
}
// similar for class KeyScreenDisplayer{...} etc.
class DoubleDispatch
{
static void Main(string[] args)
{
KeyConsolePrinter kp = new KeyConsolePrinter();
KeyBase b = new KeyBase(kp);
KeyBase a = new KeyA(kp);
KeyBase e = new KeyExtra(kp);
// Uninteresting, direkt case: We know at compile time
// what each object is and could simply call kp.Output(a) etc.
Console.Write("base:\t\t");
b.Output();
Console.Write("KeyA:\t\t");
a.Output();
Console.Write("KeyExtra:\t");
e.Output();
List<KeyI> list = new List<KeyI>() { b, a, e };
Console.WriteLine("\nb,a,e through KeyI:");
// Interesting case: We would normally not know which
// type each element in the vector has. But each type's specific
// Output() method is called -- and we know it must have
// one because that's part of the interface signature.
// Inside each type's Output() method in turn, the correct
// OutputterI::Output() for the given real type was
// chosen at compile time dpending on the type of the respective
// "this"" argument.
foreach (var k in list) { k.Output(); }
}
}
}
Sample output:
base: Got an unknown key type
KeyA: KeyA Data
KeyExtra: KeyB Data, KeyB Extra Data
b,a,e through KeyI:
Got an unknown key type
KeyA Data
KeyB Data, KeyB Extra Data

.NET Core: attributes that execute before and after method

In Java, it is possible to use AspectJ for adding behavior before and after executing a method, using method annotations. Since C# Attributes seem to be very similar, I was wondering whether it would be possible to achieve similar behavior. I was looking in several tutorials and other sources (1, 2, 3), but none of them helped me.
I thought that maybe I could be able to mimic the behavior by inserting the code into Attribute constructor and making it disposable, like this:
[AttributeUsage(AttributeTargets.Method)]
public class MyWritingAttribute : Attribute, IDisposable
{
public MyWritingAttribute()
{
Console.WriteLine("Attribute created");
}
public void Dispose()
{
Console.WriteLine("Attribute disposed");
}
}
However, when using the attribute like this, only Hello world! got displayed in the console:
class Program
{
static void Main(string[] args)
{
SayHelloWorld();
Console.ReadLine();
}
[MyWriting]
private static void SayHelloWorld()
{
Console.WriteLine("Hello World!");
}
}
I was thinking that maybe Console is not reachable in the attribute, but even when replacing it with throw new Exception() expressions, no exception was thrown. How is it possible that StringLengthAttribute from EF works, but my attribute is not even instantiated? And how do I make the attribute run before and after the decorated method?
You need some framework that is able to handle your attribute appropriately. Only because the attribute exists doesn´t mean it will have any affect.
I wrote some easy engine that does that. It will determine if the attribute is present on the passed action and if so get the reflected methods in order to execute them.
class Engine
{
public void Execute(Action action)
{
var attr = action.Method.GetCustomAttributes(typeof(MyAttribute), true).First() as MyAttribute;
var method1 = action.Target.GetType().GetMethod(attr.PreAction);
var method2 = action.Target.GetType().GetMethod(attr.PostAction);
// now first invoke the pre-action method
method1.Invoke(null, null);
// the actual action
action();
// the post-action
method2.Invoke(null, null);
}
}
public class MyAttribute : Attribute
{
public string PreAction;
public string PostAction;
}
Of course you need some null-ckecks, e.g. in the case the methods don´t exist or aren´t static.
Now you have to decorate your action with the attribute:
class MyClass
{
[MyAttribute(PreAction = "Handler1", PostAction = "Handler2")]
public void DoSomething()
{
}
public static void Handler1()
{
Console.WriteLine("Pre");
}
public static void Handler2()
{
Console.WriteLine("Post");
}
}
Finally you can execute that method within our engine:
var engine = new Engine();
var m = new MyClass();
engine.Execute(m.DoSomething);
Just like with Java and AspectJ, you need separate AoP tooling to inject code like this in .NET.
PostSharp is one such tool, probably the best known. I belive they have support for .NET core since version 5.
This can be accomplished using DynamicProxy.
There is an implementation of a memory caching technique with logic that executes before the method being called. That can be extended to check for the existence of an attribute like this
var attribute = Attribute.GetCustomAttribute(invocation.MethodInvocationTarget, typeof(CachedAttribute)) as CachedAttribute;
if (attribute != null)
{
...
}
The code above can be inside the Intercept method in the Interceptor implementation. CachedAttribute would be your attribute.
The question is similar to Run a method before all methods of a class, hence the same answer applies to both.
Use https://github.com/Fody/Fody . The licencing model is based on voluntary contributions making it the better option to PostSharp which is a bit expensive for my taste.
[module: Interceptor]
namespace GenericLogging
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
public class InterceptorAttribute : Attribute, IMethodDecorator
{
// instance, method and args can be captured here and stored in attribute instance fields
// for future usage in OnEntry/OnExit/OnException
public void Init(object instance, MethodBase method, object[] args)
{
Console.WriteLine(string.Format("Init: {0} [{1}]", method.DeclaringType.FullName + "." + method.Name, args.Length));
}
public void OnEntry()
{
Console.WriteLine("OnEntry");
}
public void OnExit()
{
Console.WriteLine("OnExit");
}
public void OnException(Exception exception)
{
Console.WriteLine(string.Format("OnException: {0}: {1}", exception.GetType(), exception.Message));
}
}
public class Sample
{
[Interceptor]
public void Method(int test)
{
Console.WriteLine("Your Code");
}
}
}
[TestMethod]
public void TestMethod2()
{
Sample t = new Sample();
t.Method(1);
}

How can this class be designed better?

We have a Web API library, that calls into a Business/Service library(where our business logic is located), which in turn calls a Data access library (Repository).
We use this type of data transfer object all over the place. It has a "Payers" property that we may have to filter (meaning, manipulate its value). I have gone about implementing that check as such, but it feels dirty to me, as I'm calling the same function all over the place. I have thought about either:
Using an attribute filter to handle this or
Making the RequestData a property on the class, and do the filtering in the constructor.
Any additional thoughts or design patterns where this could be designed more efficiently:
public class Example
{
private MyRepository _repo = new MyRepository();
private void FilterRequestData(RequestData data)
{
//will call into another class that may or may not alter RequestData.Payers
}
public List<ReturnData> GetMyDataExample1(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample1(data);
}
public List<ReturnData> GetMyDataExample2(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample2(data);
}
public List<ReturnData> GetMyDataExample3(RequestData data)
{
FilterRequestData(RequestData data);
return _repo.GetMyDataExample3(data);
}
}
public class RequestData
{
List<string> Payers {get;set;}
}
One way of dealing with repeated code like that is to use a strategy pattern with a Func (and potentially some generics depending on your specific case). You could refactor that into separate classes and everything but the basic idea looks like that:
public class MyRepository
{
internal List<ReturnData> GetMyDataExample1(RequestData arg) { return new List<ReturnData>(); }
internal List<ReturnData> GetMyDataExample2(RequestData arg) { return new List<ReturnData>(); }
internal List<ReturnData> GetMyDataExample3(RequestData arg) { return new List<ReturnData>(); }
}
public class ReturnData { }
public class Example
{
private MyRepository _repo = new MyRepository();
private List<ReturnData> FilterRequestDataAndExecute(RequestData data, Func<RequestData, List<ReturnData>> action)
{
// call into another class that may or may not alter RequestData.Payers
// and then execute the actual code, potentially with some standardized exception management around it
// or logging or anything else really that would otherwise be repeated
return action(data);
}
public List<ReturnData> GetMyDataExample1(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample1);
}
public List<ReturnData> GetMyDataExample2(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample2);
}
public List<ReturnData> GetMyDataExample3(RequestData data)
{
// call the shared filtering/logging/exception mgmt/whatever code and pass some additional code to execute
return FilterRequestDataAndExecute(data, _repo.GetMyDataExample3);
}
}
public class RequestData
{
List<string> Payers { get; set; }
}
This sort of thinking naturally leads to aspect oriented programming.
It's specifically designed to handle cross-cutting concerns (e.g. here, your filter function cuts across your query logic.)
As #dnickless suggests, you can do this in an ad-hoc way by refactoring your calls to remove the duplicated code.
More general solutions exist, such as PostSharp which give you a slightly cleaner way of structuring code along aspects. It is proprietary, but I believe the free tier gives enough to investigate an example like this. At the very least it's interesting to see how it would look in PostSharp, and whether you think it improves it at all! (It makes strong use of attributes, which extends first suggestion.)
(N.B. I'm not practically suggesting installing another library for a simple case like this, but highlighting how these types of problems might be examined in general.)

Designing different Factory classes (and what to use as argument to the factories!)

Let's say we have the following piece of code:
public class Event { }
public class SportEvent1 : Event { }
public class SportEvent2 : Event { }
public class MedicalEvent1 : Event { }
public class MedicalEvent2 : Event { }
public interface IEventFactory
{
bool AcceptsInputString(string inputString);
Event CreateEvent(string inputString);
}
public class EventFactory
{
private List<IEventFactory> factories = new List<IEventFactory>();
public void AddFactory(IEventFactory factory)
{
factories.Add(factory);
}
//I don't see a point in defining a RemoveFactory() so I won't.
public Event CreateEvent(string inputString)
{
try
{
//iterate through all factories. If one and only one of them accepts
//the string, generate the event. Otherwise, throw an exception.
return factories.Single(factory => factory.AcceptsInputString(inputString)).CreateEvent(inputString);
}
catch (InvalidOperationException e)
{
throw new InvalidOperationException("Either there was no valid factory avaliable or there was more than one for the specified kind of Event.", e);
}
}
}
public class SportEvent1Factory : IEventFactory
{
public bool AcceptsInputString(string inputString)
{
return inputString.StartsWith("SportEvent1");
}
public Event CreateEvent(string inputString)
{
return new SportEvent1();
}
}
public class MedicalEvent1Factory : IEventFactory
{
public bool AcceptsInputString(string inputString)
{
return inputString.StartsWith("MedicalEvent1");
}
public Event CreateEvent(string inputString)
{
return new MedicalEvent1();
}
}
And here is the code that runs it:
static void Main(string[] args)
{
EventFactory medicalEventFactory = new EventFactory();
medicalEventFactory.AddFactory(new MedicalEvent1Factory());
medicalEventFactory.AddFactory(new MedicalEvent2Factory());
EventFactory sportsEventFactory = new EventFactory();
sportsEventFactory.AddFactory(new SportEvent1Factory());
sportsEventFactory.AddFactory(new SportEvent2Factory());
}
I have a couple of questions:
Instead of having to add factories
here in the main method of my
application, should I try to
redesign my EventFactory class so it
is an abstract factory? It'd be
better if I had a way of not having
to manually add
EventFactories every time I want to
use them. So I could just instantiate MedicalFactory and SportsFactory. Should I make a Factory of factories? Maybe that'd be over-engineering?
As you have probably noticed, I am using a inputString string as argument to feed the factories. I have an application that lets the user create his own events but also to load/save them from text files. Later, I might want to add other kinds of files, XML, sql connections, whatever. The only way I can think of that would allow me to make this work is having an internal format (I choose a string, as it's easy to understand). How would you make this? I assume this is a recurrent situation, probably most of you know of any other more intelligent approach to this. I am then only looping in the EventFactory for all the factories in its list to check if any of them accepts the input string. If one does, then it asks it to generate the Event.
If you find there is something wrong or awkward with the method I'm using to make this happen, I'd be happy to hear about different implementations. Thanks!
PS: Although I don't show it in here, all the different kind of events have different properties, so I have to generate them with different arguments (SportEvent1 might have SportName and Duration properties, that have to be put in the inputString as argument).
I am not sure about the input string question but for the first question you can likely use "convention over configuration"; a combination of reflection, the IEventFActory type and the naming you already have in place, Name.EndsWith("EventFactory") should allow you to instantiate the factories and get them into their Lists with code.
HTH ,
Berryl

Categories

Resources