Lets say I have this interface
public interface ITest
{
int Property1 { get; set; }
void Method1();
string GetMethod1();
void MethodWithParam(string str);
}
How can I create a wrapper object around this?
And then capture the methods called or paramters and values accessed etc.
For example:
var myWrapper = GetWrapper<ITest>();
myWrapper.Property1 = 7;
How would I be able to using reflection or whatever to know the following:
Paramter name being called and value being set
var data = myWrapper.GetMethod1("Test");
Get method name of "GetMethod1" along with paramaters and then return a value based on that?
Hope makes sense
Ok so answer quite simple using Castle Core proxy generator:
https://github.com/castleproject/Core
public interface ITest
{
int Property1 { get; set; }
void Method1();
string GetMethod1();
void MethodWithParam(string str);
}
public static class Wrapper
{
private class MethodInterceptor : IInterceptor
{
Action<IInvocation> OnIntercept;
public MethodInterceptor(Action<IInvocation> OnIntercept)
{
this.OnIntercept = OnIntercept;
}
public void Intercept(IInvocation invocation)
{
OnIntercept?.Invoke(invocation);
}
}
private static void CallAPI(IInvocation invocation)
{
var methodName = invocation.Method.Name;
var valuespassed = invocation.Arguments;
var retType = invocation.Method.ReturnType.FullName;
//DO API THINGS NOW
}
public static T Get<T>()
{
ProxyGenerator generator = new ProxyGenerator();
var interceptor = new MethodInterceptor(CallAPI);
var c = generator.CreateInterfaceProxyWithoutTarget<ITest>(interceptor);
return (T)c;
}
}
public class Test123
{
public void Test()
{
var c = Wrapper.Get<ITest>();
c.Property1 = 7;
var propval = c.Property1;
}
}
Any action on c calls the intercept function where can get everything from method name being called to arguments passed.
Related
I can do this with StructureMap using Constructor Injection. However I cannot find a way to do this with Simple Injector. Here is some code that illustrates this (sorry for the length)
I've looked at the lambda in the Register method, but can't seem to understand how to call a single application wide instance of the container to get the one instance I need.
These are the object graphs I wish to construct:
var bannerTalker =
new LoudMouth(
new ConsoleShouter(), // Implements IConsoleVoicer
new ObnoxiousBannerGenerator());
var plainTalker =
new TimidSpeaker(
new ConsoleWhisperer()); // Implements IConsoleVoicer
Here's the code:
``` c#
public interface IConsoleVoicer
{
void SaySomething(string whatToSay);
}
public class ConsoleWhisperer : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToLower());
}
}
public class ConsoleShouter : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToUpper());
}
}
public interface IBannerGenerator
{
string GetBanner();
}
public class ObnoxiousBannerGenerator : IBannerGenerator
{
public string GetBanner()
{
return "OBNOXIOUS";
}
}
public interface IBannerTalker
{
void SayWithBanner(string somethingToSay);
}
public class LoudMouth : IBannerTalker
{
private IConsoleVoicer Voicer { get; set; }
private IBannerGenerator BannerGenerator { get; set; }
public LoudMouth(
IConsoleVoicer concoleVoicer, IBannerGenerator bannerGenerator)
{
Voicer = concoleVoicer;
BannerGenerator = bannerGenerator;
}
public void SayWithBanner(string somethingToSay)
{
Voicer.SaySomething(string.Format("{0}:{1}",
BannerGenerator.GetBanner(), somethingToSay));
}
}
public interface IPlainTalker
{
void SayIt(string somethingToSay);
}
public class TimidSpeaker : IPlainTalker
{
private IConsoleVoicer Voicer { get; set; }
public TimidSpeaker(IConsoleVoicer concoleVoicer)
{
Voicer = concoleVoicer;
}
public void SayIt(string somethingToSay)
{
Voicer.SaySomething(somethingToSay);
}
}
And this is what I've tried:
static void Main(string[] args)
{
var container = new Container();
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
//HERE IS THE DILEMMA! How do I assign
// to IBannerTalker a A LoudMouth contructed with a ConsoleShouter,
// and to IPlainTalkerTalker a A TimidSpeaker contructed with a ConsoleWhisperer
//container.Register<IConsoleVoicer, ConsoleShouter>();
container.Register<IConsoleVoicer, ConsoleWhisperer>();
var bannerTalker = container.GetInstance<IBannerTalker>();
var plainTalker = container.GetInstance<IPlainTalker>();
bannerTalker.SayWithBanner("i am a jerk");
plainTalker.SayIt("people like me");
}
Ric .Net is right in pointing you at the RegisterConditional methods. The following registrations complete your quest:
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
container.RegisterConditional<IConsoleVoicer, ConsoleShouter>(
c => c.Consumer.ImplementationType == typeof(LoudMouth));
container.RegisterConditional<IConsoleVoicer, ConsoleWhisperer>(
c => c.Consumer.ImplementationType == typeof(TimidSpeaker));
//Program.cs
public interface TestVal
{
//Input Param
string Input { get; }
//will return output
TestValRes ValidateRe(string input);
}
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
//TestvalRes.cs
public interface TestvalRes
{
string Input { get; }
bool IsValid { get; }
}
So I just want to pass a string to the TestVal, do validation and call TestvalRes to return whether it is Valid or not, and if Invalid, why? So the validation will be done in the first public interface - TestVal, however I still need to call it inside the Main(), right?
First off, I'd recommend following C# naming conventions and name your interfaces ITestVal and ITestValRes respectively.
Next, static method cannot call instance methods in the same class (without creating an instance and using that). You need to create an instance of the class and pass control of the application flow to that:
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
I would like to set an event handler only by reflection, I can get all the types but I can't achieve it.
public delegate void MyHandler<T>(IMyInterface<T> pParam);
public interface IMyInterface<T>
{
MyHandler<T> EventFired { get; set; }
}
void myFunction()
{
//admit vMyObject is IMyInterface<ClassA>
var vMyObject = vObj as IMyInterface<ClassA>;
//get the generic type => ClassA
var vTypeGeneric = vTypeReturn.GenericTypeArguments.FirstOrDefault();
//build the type handler for the event MyHandler<ClassA>
Type vAsyncOP = typeof(MyHandler<>).MakeGenericType(vTypeGeneric);
// here I don't know how to create the Event handler to set EventFired
// dynamically with the code inside
var vEventFired = vMyObject.GetType().GetProperty("EventFired");
vEventFired.SetMethod etc...
}
I found some code with the usage of Lambda/Expression but I don't understand how to use it in this case.
Full sample:
public delegate void MyHandler<T>(IMyInterface<T> pParam);
public interface IMyInterface<T>
{
MyHandler<T> EventFired { get; set; }
}
public class MyClass : IMyInterface<int>
{
public MyHandler<int> EventFired { get; set;}
}
public void ConcreteHandler(IMyInterface<int> p)
{
Console.WriteLine("I'm here");
}
void Main()
{
var myValue = new MyClass();
var deleg = Delegate.CreateDelegate(typeof(MyHandler<int>), this, "ConcreteHandler");
myValue.GetType().GetProperty("EventFired").SetValue(myValue, deleg);
// Test delegate invocation:
myValue.EventFired.Invoke(new MyClass());
}
Since the question asks about setting an event and the code refers to delegate, here is the code for setting an event using reflection (via extension method):
public delegate void MyHandler<T>(IMyInterface<T> pParam);
public interface IMyInterface<T>
{
event MyHandler<T> EventFired;
}
public class ClassA : IMyInterface<int>
{
public event MyHandler<int> EventFired;
private int _Count = 0;
public void Fire()
{
var handler = EventFired;
if (handler != null) handler(this);
}
public override string ToString()
{
return "Call: " + (++_Count).ToString();
}
}
public static class Extension
{
public static void Add<T>(this IMyInterface<T> i, System.Reflection.MethodInfo method, object method_instance = null)
{
if (method.IsGenericMethodDefinition) method = method.MakeGenericMethod(typeof(T));
Delegate d = Delegate.CreateDelegate(typeof(MyHandler<>).MakeGenericType(typeof(T)), method_instance, method);
i.GetType().GetEvent("EventFired").GetAddMethod().Invoke(i, new object[] { d });
}
}
public class Program
{
public static void Print<T>(IMyInterface<T> val)
{
string output = val.ToString();
Console.WriteLine(output);
System.Diagnostics.Debug.WriteLine(output);
}
static void Main(string[] args)
{
ClassA ca = new ClassA();
ca.EventFired += Print<int>;
ca.Add(typeof(Program).GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public));
ca.Fire();
}
}
Sorry for the title, I meant not an event but a delegate property.
I found the solution meanwhile :
public void MyDelegate<T>(IMyInterface<T> pParam)
{
}
void myFunction()
{
//admit vMyObject is IMyInterface<ClassA>
var vMyObject = vObj as IMyInterface<ClassA>;
//get the generic type => ClassA
var vTypeGeneric = vTypeReturn.GenericTypeArguments.FirstOrDefault();
//build the type handler for the event MyHandler<ClassA>
Type vAsyncOP = typeof(MyHandler<>).MakeGenericType(vTypeGeneric);
// SOLUTION here :
// Create MyDelegate<vTypeGeneric>
// Then instanciate it with CreateDelegate and typeof(IMyInterface<vTypeGeneric>)
var vMyDelegate= this.GetType().GetMethod("MyDelegate");
var vMyDelegateGeneric = vMyDelegate.MakeGenericMethod(vTypeGeneric);
Type vTypeHandlerGeneric = typeof(IMyInterface<>).MakeGenericType(vTypeGeneric);
// this => bind to method in the class
var vMethodDelegate = vMyDelegateGeneric.CreateDelegate(vTypeHandlerGeneric, this);
// Set delegate Property
var vEventFired = vMyObject.GetType().GetProperty("EventFired");
vEventFired.SetValue(value, vDelegate);
}
My brain is gonna to explode. :) So I would like to get help from you.
Please, think about my question like about just programmer puzzle. (Actually. perhaps it is very easy question for you, but not for me.)
It is needed to create array of objects. For example List where T is class. (I will describe Class T below). Also it is needed create “container” that will contain this array and some methods for work with this array. For example Add(), Remove(int IndexToRemove).
Class T must have field "Container", this way each elements of our array would be able to know where is it contained and has access its container's fields and methods. Notice, that in this case Class T should have type parameter. Indeed, it is not known beforehand which container's type is used.
Let us denote this class container as A and class element (class T) as AUnit.
Code:
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a.Units[0].SomeField +=100;
Console.ReadKey();
}
}
class A
{
public List<AUnit> Units;
public A()//ctor
{
Units = new List<AUnit>();
}
public void Add()
{
this.Units.Add(new AUnit(this));
}
}
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
}
Public fields should be protected or private of course, but let think about this later.
You can ask “why we create public A Container field in AUnit”? We create field public string Name{get;private set;} (actually property but nevermind). And also we would like to be able to change value of this field for example method [Class AUnit] public bool Rename(string newName)();. The main idea of this method is changing Name field only that case if no one element in array (public List Units; ) has the same name like newName. But to achieve this, Rename method has to have access to all names that is currently used. And that is why we need Container field.
Code of extended version AUnit
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.Units)
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
Ok. If you still read it let's continue. Now we need to create Class B and class BUnit which will be very similar like Class A and Class Aunit. And finally the main question of this puzzle is HOW WE CAN DO IT? Of course, I can CopyPaste and bit modify A and AUnit and create this code.
class B
{
public List<BUnit> Units; //Only Type Changing
public B()//ctor Name changing...
{
Units = new List<BUnit>();//Only Type Changing
}
public void Add()
{
this.Units.Add(new BUnit(this));//Only Type Changing
}
}
class BUnit
{
public int SomeField;
public B Container;//Only Type Changing
public string Name { get; private set; }
public A a; //NEW FIELD IS ADDED (just one)
public BUnit(B container) //Ctor Name and arguments type changing
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
this.a=new A(); //New ROW (just one)
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (BUnit unt in this.Container.Units) //Only Type Changing
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
And I can to use this classes this way.
static void Main(string[] args)
{
B b = new B();
b.Add();
b.Units[0].a.Add();
b.Units[0].a.Units[0].SomeField += 100;
bool res= b.Units[0].a.Units[0].Rename("1");
res = b.Units[0].a.Units[0].Rename("1");
Console.ReadKey();
}
This construction is can be used to create “non-homogeneous trees”.
Help, I need somebody help, just no anybody…. [The Beatles]
I created B and BUnit using CopyPaste.
But how it can be done using “macro-definitions” or “Generic”, inherit or anything else in elegant style? (C# language)
I think that there is no reason to describe all my unsuccessful attempts and subquestions. Already topic is too long. : )
Thanks a lot if you still read it and understand what I would like to ask.
You need to implement a base type, lets call it UnitBase, with all common functionality. I'd structure your code the following way:
Create an interface for your container, this way you can change implementation to more performant solutions without modifying the elements you will be adding to the container.
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
}
Following the idea stated in 1, why not make the search logic belong to the container? It makes much more sense, as it will mostly depend on how the container is implemented:
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
bool Contains(string name);
}
A specific implementation of IContainer could be the following:
public class Container : IContainer
{
public Container()
{
list = new List<UnitBase>();
}
private List<UnitBase> list;
public Q Add<Q>() where Q: UnitBase, new()
{
var newItem = Activator.CreateInstance<Q>();
newItem.SetContainer(this);
list.Add(newItem);
return newItem;
}
public IEnumerable<UnitBase> Units => list.Select(i => i);
public bool Contains(string name) =>
Units.Any(unit => unit.Name == name);
}
Create a base class for your AUnit and BUnit types condensing all common functionality:
public abstract class UnitBase
{
protected UnitBase()
{
}
public IContainer Container { get; private set; }
public int SomeField;
public string Name { get; private set; }
public void SetContainer(IContainer container)
{
Container = container;
}
public bool Rename(String newName)
{
if (Container.Contains(newName))
return false;
this.Name = newName; //No need to use String.Copy
return true;
}
}
Implement your concrete types:
public class BUnit : UnitBase
{
public int SpecificBProperty { get; private set; }
public BUnit()
{
}
}
Shortcomings of this approach? Well, the container must be of type <UnitBase>, I've removed the generic type because it really wasn't doing much in this particular case as it would be invariant in the generic type.
Also, keep in mind that nothing in the type system avoids the following:
myContainer.Add<BUnit>();
myContainer.Add<AUnit>();
If having two different types in the same container is not an option then this whole set up kind of crumbles down. This issue was present in the previous solution too so its not something new, I simply forgot to point it out.
InBetween , I am very thankful to you for your advices. Actually I can't say that I understood your answer in full, but using your ideas I have done what I want.
Looks like my variant works well. However I would like to hear your (and everyone) opinions about code described below. The main goal of this structure is creating non-homogeneous trees. So could you estimate it from this side.
First of all. We need to create interfaces for both classes. We describe there all "cross-used" functions.
public interface IUnit<T>
{
string Name { get;}
void SetContainer(T t);
bool Rename(String newName);
}
public interface IContainer
{
bool IsNameBusy(String newName);
int Count { get; }
}
Next. Create Base for Unit Classes for future inheritance. We will use in this inheritors methods from Container Base so we need generic properties and IUnit interface.
class UnitBase<T> : IUnit<T> where T : IContainer
Unfortunately I don't know yet how to solve the problem with Constructor parameters. That is why I use method
SetContainer(T container).
Code:UnitBase
class UnitBase<T> : IUnit<T> where T : IContainer
{
protected T Container;
public string Name { get; private set; }
public UnitBase()
{
this.Name = "Default";
}
public void SetContainer(T container)
{
this.Container = container;
}
public bool Rename(String newName)
{
bool res = Container.IsNameBusy(newName);
if (!res) this.Name = String.Copy(newName);
return !res;
}
}
Next. Create ContainerBase
ContainerBase should:
1) has IContainer interface.
2)has information about what it will contain:
... where U : IUnit<C>, new()
3)and .... has information about what itself is. This information we need to pass as parameter to SetContainer() method.
Code ContainerBase:
class ContainerBase<U, C> : IContainer //U - Unit Class. C-Container Class
where U : IUnit<C>, new()
where C : ContainerBase<U, C>
{
protected List<U> Units;
public U this[int index] { get { return Units[index]; } }
public ContainerBase()//ctor
{
this.Units = new List<U>();
}
public void Add()
{
this.Units.Add(new U());
this.Units.Last().SetContainer(((C)this));//may be a bit strange but actualy this will have the same type as <C>
}
public bool IsNameBusy(String newName)
{
bool res = false;
foreach (var unt in this.Units)
{
if (unt.Name == newName)
{
res = true;
break;
}
}
return res;
}
public int Count { get { return this.Units.Count; } }
}
Cast ((TContainer)(this)) may be is a bit strange. But using ContainerBase we always should use NewInheritorContainer. So this cast is just do nothing…looks like...
Finally. This classes can be used like in this example.
class SheetContainer : ContainerBase<SheetUnit,SheetContainer> {public SheetContainer(){}}
class SheetUnit : UnitBase<SheetContainer>
{
public CellContainer Cells;
public PictureContainer Pictures;
public SheetUnit()
{
this.Cells = new CellContainer();
this.Pictures = new PictureContainer();
}
}
class CellContainer : ContainerBase<CellUnit, CellContainer> { public CellContainer() { } }
class CellUnit : UnitBase<CellContainer>
{
public string ValuePr;//Private Field
private const string ValuePrDefault = "Default";
public string Value//Property for Value
{
//All below are Just For Example.
get
{
return this.ValuePr;
}
set
{
if (String.IsNullOrEmpty(value))
{
this.ValuePr = ValuePrDefault;
}
else
{
this.ValuePr = String.Copy(value);
}
}
}
public CellUnit()
{
this.ValuePr = ValuePrDefault;
}
}
class PictureContainer : ContainerBase<PictureUnit, PictureContainer> { public PictureContainer() { } }
class PictureUnit : UnitBase<PictureContainer>
{
public int[,] Pixels{get;private set;}
public PictureUnit()
{
this.Pixels=new int[,]{{10,20,30},{11,12,13}};
}
public int GetSizeX()
{
return this.Pixels.GetLength(1);
}
public int GetSizeY()
{
return this.Pixels.GetLength(0);
}
public bool LoadFromFile(string path)
{
return false;
}
}
static void Main(string[] args)
{
SheetContainer Sheets = new SheetContainer();
Sheets.Add();
Sheets.Add();
Sheets.Add();
Sheets[0].Pictures.Add();
Sheets[1].Cells.Add();
Sheets[2].Pictures.Add();
Sheets[2].Cells.Add();
Sheets[2].Cells[0].Value = "FirstTest";
bool res= Sheets[0].Rename("First");//res=true
res=Sheets[2].Rename("First");//res =false
int res2 = Sheets.Count;
res2 = Sheets[2].Pictures[0].Pixels[1, 2];//13
res2 = Sheets[2].Pictures.Count;//1
res2 = Sheets[1].Pictures.Count;//0
res2 = Sheets[0].Pictures[0].GetSizeX();//3
Console.ReadKey();
}
Looks like it works like I want. But I didn’t test it full.
Let me say Thank you again, InBetween.
What it boils down to is that I'm trying to make a Generic and while the type shows up correctly at runtime, during compile time its still object, and so I cannot use any of the generic type's methods.
thanks to brainless coder on a previous question I'm able to move forward a bit
dotnetfiddle
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var sample = new Baz<List<Foo>>();
sample.DoSomething();
}
public class Foo
{
}
public class Bar<T>
{
public void Boom()
{
}
}
public class Baz<T>
{
public void DoSomething(){
if (typeof(T).Name == "List`1")
{
var typeName = typeof(T).GetGenericArguments().Single().FullName;
var type = Type.GetType(typeName);
var genericRepoType = typeof(Bar<>);
var specificRepoType = genericRepoType.MakeGenericType(new Type[] { type });
var genericBar = Activator.CreateInstance(specificRepoType);
Console.WriteLine(genericBar.GetType().Name); // Shows Bar`1
// but at compile time its foo is still an object
genericBar.Boom();
//will error with 'object' does not contain a definition for Boom
}
}
}
}
This sounds like a very questionable design, but if you must, dynamic neatly solves your problem.
public static void Main() {
var sample = new Baz<List<Foo>>();
sample.DoSomething();
}
public class Foo { }
public class Bar<T> {
public void Boom() {
Console.WriteLine("I am booming");
}
}
public class Baz<T> {
public void DoSomething() {
var typeName = typeof(T).GetGenericArguments().Single().FullName;
var type = Type.GetType(typeName);
var genericRepoType = typeof(Bar<>);
var specificRepoType = genericRepoType.MakeGenericType(new Type[] { type });
dynamic genericBar = Activator.CreateInstance(specificRepoType);
Console.WriteLine(genericBar.GetType().Name);
genericBar.Boom();
}
}
https://dotnetfiddle.net/uPpfJa
Alternatively, you could declare an IBar interface.
public class Bar<T> : IBar {
public void Boom() {
Console.WriteLine("I am booming");
}
}
interface IBar {
void Boom();
}
...
var genericBar = (IBar)Activator.CreateInstance(specificRepoType);