I have this code (its just part, entire code works just fine):
internal static Rule<IWorkflowModel> Get()
{
var rule = new Rule<IWorkflowModel>("Argument Naming Rule", RuleId, Inspect)
{
DefaultErrorLevel = System.Diagnostics.TraceLevel.Warning,
RecommendationMessage = Recommendation
};
return rule;
}
private static InspectionResult Inspect(IWorkflowModel workflowModel, Rule ruleInstance)
{
I am trying to understand, how can we pass Inspect static method as parameter in line 3, without adding parameters to itself (like Inspect(paramA, paramB)?
I can guess it takes both Rule and IWorkflowModel objects from the rule created itself (line 3). But trying to figure out some logic/rule behind it.
Edit
This is Rule<T> class from metadata
namespace UiPath.Studio.Activities.Api.Analyzer.Rules
{
public sealed class Rule<T> : Rule where T : IInspectionObject
{
public Rule(string ruleName, string ruleId, Func<T, Rule, InspectionResult> inspectionFunction);
public Func<T, Rule, InspectionResult> Inspect { get; }
}
}
You're passing the function, not invoking it. This allows a different piece of code to invoke the function later, supplying the arguments.
The way this is done in C# is through delegates (since about .NET 3.5, instead of using custom delegate types, you will probably want to use Action and Func respectively). You can think of a delegate as a single-method interface - it's basically a bridge between object-oriented and true functional programming.
In older code, this was mainly used in events and callbacks. Today, as C# gets more and more functional, it's getting rather common for abstract functions to accept functions as arguments; LINQ was probably the first big example. You supply your own behaviour to other functions. You want to filter a collection? Just pass a function that does the filtering (col.Where(i => i.Name.Length > 3)).
To show you a possible way of implementing what you're seeing in your code:
public class Rule<T> : Rule
{
private readonly Func<T, Rule, InspectionResult> _inspect;
public Rule(string name, string ruleId, Func<T, Rule, InspectionResult> inspect)
: base(name, ruleId)
{
_inspect = inspect;
}
public InspectionResult Inspect(T model) => _inspect(this, model);
}
Note that when Rule<T> calls the delegate, it must supply all of the arguments.
Of course, the actual behaviour of the caller can be essentially arbitrary. The point is that you're passing a behaviour to someone else. Delegates are a very simple and quick way of doing that, especially combined with anonymous functions and all that.
Related
Reading a Previous SO Question I was confused to find Eric Lippert saying that an interface cannot be defined in C# for all Monads, using an implementation as below:
typeInterface Monad<MonadType<A>>
{
static MonadType<A> Return(A a);
static MonadType<B> Bind<B>(MonadType<A> x, Func<A, MonadType<B>> f);
}
My problem is all the problems listed in the question seem to have easy solutions:
no "higher kinded types" => use parent interfaces
no static method in interface. => why use static?! just use instance methods
Monad is a pattern allowing chaining of operations on wrapped types
it seems easy to define a C# interface for all Monads allowing us to write a generic class for all monads
Where's the problem?
using System;
using System.Linq;
public class Program
{
public static void Main()
{//it works, where's the problem?
new SequenceMonad<int>(5)
.Bind(x => new SequenceMonad<float>(x + 7F))
.Bind(x => new SequenceMonad<double>(x + 5D))
;
}
interface IMonad<T>{
IMonad<T> Wrap(T a);
IMonad<U> Bind<U>(Func<T, IMonad<U>> map);
T UnWrap();//if we can wrap we should be able to unwrap
}
class GenericClassForAllMonads<T>
{//example writing logic for all monads
IMonad<U> DoStuff<U>(IMonad<T> input, Func<T, IMonad<U>> map)
{ return map(input.UnWrap()); }
}
class SequenceMonad<T> : IMonad<T> where T:new()
{//specific monad implementation
readonly T[] items;//immutable
public SequenceMonad(T a)
{
Console.WriteLine("wrapped:"+a);
items = new[] { a };
}
public IMonad<B> Bind<B>(Func<T, IMonad<B>> map)
{ return map(UnWrap()); }
public T UnWrap()
{ return items == null? default(T) : items.FirstOrDefault(); }
public IMonad<T> Wrap(T a)
{
Console.WriteLine("wrapped:"+a);
return new SequenceMonad<T>(a);
}
}
}
it seems easy to define a C# interface for all monads. Where's the problem?
Your proposal is:
interface IMonad<T>
{
IMonad<T> Wrap(T a);
IMonad<U> Bind<U>(Func<T, IMonad<U>> map);
}
I've omitted the "unwrap" because the existence of an extraction operation is not a requirement of a monad. (Many monads have this operation, but not all do. If you require an extract operation, you are probably actually using a comonad.)
You ask why this is wrong. This is wrong in several ways.
The first way it is wrong is: there is no way to create a new instance of the monad via Wrap without already having an instance! You have a chicken-and-egg problem here.
The "wrap" or "unit" or "return" operation -- whatever you want to call it -- is logically a static factory; it's how you make a new instance of the monad. It's not an operation on an instance. It is a requirement of a static method on a type. (Or, the requirement that a type implement a particular constructor, which is effectively the same thing. Either way, it is not supported in C# at this time.)
Let's eliminate Wrap from consideration in the next point. Why is Bind wrong?
The second way it is wrong is you do not have the right restrictions in place. Your interface says that a monad of T is a thing that provides a bind operation that returns a monad of U. But that is not restrictive enough! Suppose we have a monad Maybe<T> : IMonad<T>. Now suppose we have this implementation:
class Wrong<T> : IMonad<T>
{
public IMonad<U> Bind<U>(Func<T, IMonad<U>> map)
{
return new Maybe<U>();
}
}
That satisfies the contract, which tells us that the contract is not the real monad contract. The monad contract should be that Wrong<T>.Bind<U> returns Wrong<U>, not IMonad<U>! But we have no way of expressing in C# "bind returns an instance of the class which defines bind".
Similarly it is wrong because the Func that is provided by the caller must be required to return Wrong<U>, not IMonad<U>. Suppose we have a third monad, say, State<T>. We could have
Wrong<Frog> w = whatever;
var result = w.Bind<Newspaper>(t=>new State<Newspaper>());
And now this is all messed up. Wrong<T>.Bind<U> must take a function that returns some Wrong<U> and must itself return Wrong<U> of the same type, but this interface allows us to have a bind that takes a function that returns State<Newspaper> but the bind returns Maybe<Newspaper>. This is a total violation of the monad pattern. You have not captured the monad pattern in your interface.
The C# type system is not strong enough to express the constraint "when the method is implemented it must return an instance of the class that did the implementation". If C# had a "this_type" compile-time annotation then Bind could be expressed as an interface, but C# does not have that annotation.
I have a question wheater or not it is possible (and if it is, how) to access class members from inside a Func<T, TResult> delegate.
For example, I have the following class:
class NinjaTurtle
{
public string Sound { get; set; }
public Func<string, string> DoNinjaMove { get; set; }
}
Now I'd like to do this
NinjaTurtle leonardo = new NinjaTurtle();
leonardo.Sound = "swiishhh!";
leonardo.DoNinjaMove = (move) => {
if(move == "katana slash") return leonardo.Sound;
return "zirp zirp zirp";
}
The problem is, how do I correctly access the property Sound, when I define the callback function? Is it OK to just use the reference to the instance from outside the function? Would this still work when I pass the object to another method, or even when this would be part of a dll, and I would return the object leonardo from a function in the dll? Would it "survive" serialization / deserialization?
(Thanks Vladimir and Lee, the question is now more specific to what I would like to know).
You can use closures. A closure will be an anonymous delegate or lambda expression which may reference variables, methods, properties, events or anything from an outer scope (oops, it's your case!).
leonardo.DoNinjaMove = (move) => {
// THIS IS VALID! IT'S A CLOSURE! You can access leonardo reference within
// the closure!!
if(move == "katana slash") return leonardo.Sound;
return "zirp zirp zirp";
}
Anyway, DoNinjaMove is Func<string, bool>. If you want to return Sound value, it should be refactored to Func<string, string>.
Further details about how closures work and why you can safely use outer scope's references within them can be found on this other Q&A here in StackOverflow:
How do closures work behind the scenes? (C#)
About if using closures would work when working with satellite assemblies and so...
Yes, there's no problem with that. Closures are a very interesting feature that most modern languages own and it's a must-have feature for languages that have incorporated functional programming. Anyway, it's a must-have feature! :)
If you came here from Google specifically wanting to code a Lambda function as a class member declared inside the class body, read on...
I found this post through google, because I was looking for a way to declare the Lambda Func as a member method of the class itself. You can declare a Func inside of a class but you can't directly assign to it in the same line. Example:
public class myClass {
public Func<string,string> DoNinjaMove; //Can't declare method body here.
}
The solution is to assign the Lambda function body inside the Constructor of the class like this:
public class myClass {
public Func<string,string> DoNinjaMove; //Can't declare method body here.
public myClass()
{
DoNinjaMove = (someString) =>
{
//Do something here
return anotherString;
}
}
}
Now DoNinjaMove is a member of myClass and it's body is also declared inside myClass. DoNinjaMove has access to all members of myClass, and you get the ability to pass DoNinjaMove to other classes/objects for them to call it.
I probably wouldn't recommend this design pattern unless you absolutely know what you're doing. In my case, another library I was using demanded I pass it a Lambda function with a specific input and return type, but I needed the function to be a member of my own class where it had access to class data for the sake of elegance and encapsulation. This is the solution I came up with.
This will capture the variable leonardo in a closure and will work but I don't think this is a good design but it is hard to suggest something different without context.
var leonardo = new NinjaTurtle();
leonardo.Sound = "swiishhh!";
leonardo.DoNinjaMove = (move) =>
{
if (move == "katana slash")
{
return leonardo.Sound;
}
else
{
return "zirp zirp zirp";
}
}
You may want to consider using Func<NinjaTurtle, String, String> and pass the turtle in explicitly.
leonardo.DoNinjaMove = (turtle, move) =>
{
if (move == "katana slash")
{
return turtle.Sound;
}
else
{
return "zirp zirp zirp";
}
}
But this does still not look like a convincing design to me.
This has a game development project under itself, but it's really about coding and mapping data to other pieces of data. This is why I decided to post it here.
The format that I'm using for external inventory item data storage:
[ID:IT_FO_TROUT]
[Name:Trout]
[Description:A raw trout.]
[Value:10]
[3DModel:null]
[InventoryIcon:trout]
[Tag:Consumable]
[Tag:Food]
[Tag:Stackable]
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
The question is concentrated upon the last 2 OnConsume properties. Basically, the two properties mean that when the item gets consumed, the consumer's health goes up by 15 points, and his fatigue does so as well. This, in the background, invokes 2 different methods:
void RestoreHealth(Character Subject, int Amount);
void RestoreFatigue(Character Subject, int Amount);
How would you go about mapping the methods to their in-file string counterparts? This is what I thought of:
Every time an item gets consumed, a list of strings (the events) gets passed to an Item event manager. The manager parses each string and calls the appropriate methods. Very easy to set up, and since this is not an operation that happens too often, the impact on performance might not be considerable (strings will also be tiny (max 10-15 characters) in size, and parsed in O(n) time).
Each inventory item (class) parses the string events once and only once, on initialization. Each string event gets mapped to its appropriate method via a dictionary. This is the most efficient method in terms of performance that I can think of, but it makes it extremely difficult to do other things:
All of the values in the dictionary would have to be delegates of the same kind. This means I cannot keep
a) RestoreHealth(int)
b) SummonMonster(Position, Count)
in the same dictionary, and would have to set a new data structure for each kind of callable method. This is a tremendous amount of work to do.
Some ways that came to mind, to improve both methods:
I could use some sort of temporary cache inside the Item event
manager, so that an item's OnConsume events don't get parsed
twice? I might hit the same issues as the ones I hit during 2)
though, as the cache would have to be a map<InventoryItem,List<delegate>>.
The hashtable data structure inside the .NET libraries allows
for any kind of object to be a key and/or value at any given time
(unlike the dictionary). I could use this and map string A to
delegate X, while also having mapped string B to delegate Y
inside the same structure. Any reasons why I should not do this? Can
you foresee any trouble that would be brought by this method?
I was also thinking about something in the ways of reflection, but I'm not exactly experienced when it comes to it. And I'm pretty sure parsing the string every time is faster.
EDIT
My final solution, with Alexey Raga's answer in mind. Using interfaces for each kind of event.
public interface IConsumeEvent
{
void ApplyConsumeEffects(BaseCharacter Consumer);
}
Sample implementer (particular event):
public class RestoreHealthEvent : IConsumeEvent
{
private int Amount = Amount;
public RestoreHealthEvent(int Amount)
{
this.Amount = Amount;
}
public void ApplyConsumeEffects(BaseCharacter Consumer)
{
Consumer.Stats.AlterStat(CharacterStats.CharStat.Health, Amount);
}
}
Inside the parser (the only place where we care about the event's particularities - because we're parsing the data files themselves):
RestoreHealthEvent ResHealthEv = new RestoreHealthEvent (Value);
NewItem.ConsumeEvents.Add (ResHealthEv );
When a character consumes an item:
foreach (IConsumeEvent ConsumeEvent in Item.ConsumeEvents)
{
//We're inside a parent method that's inside a parent BaseCharacter class; we're consuming an item right now.
ConsumeEvent.ApplyConsumeEffects(this);
}
Why not "map" them to "command" classes once-and-only-once instead?
For example,
[OnConsume:RestoreHealth(15)]
[OnConsume:RestoreFatigue(15)]
could be mapped to RestoreHealth and RestoreFatigue command classes that can be defined as:
public sealed class RestoreHealth : ICommand {
public int Value { get; set; }
//whatever else you need
}
public sealed class SummonMonster : ICommand {
public int Count {get; set; }
public Position Position { get; set; }
}
Consider commands as just wrappers for your parameters at this point ;) So instead of passing multiple parameters you always wrap them and pass only one.
It also gives a bit of semantics too.
Now you can map your inventory items to commands that need to be "sent" when each item is consumed.
You can implement a simple "bus" interface like:
public interface IBus {
void Send(ICommand command);
void Subscribe(object subscriber);
}
and now you just get an instance of IBus and call its Send method when appropriate.
By doing this you separate your "definition" (what needs to be done) and your logic (how to perform an action) concerns.
For the receiving and reacting part you implement the Subscribe method to interrogate the subscriber instance (again, once and only once) figuring out all its method which can "handle" commands.
You can come up with some IHandle<T> where T: ICommand interface in your handlers, or just find them by convention (any Handle method that accepts only one argument of ICommand and returns void), or whatever works for you.
It is basically the same part of "delegate/action" lists that you were talking about except that now it is per command:
map<CommandType, List<action>>
Because all the actions now accept only one parameter (which is ICommand) you can easily keep them all in the same list.
When some command is received, your IBus implementation just gets the list of actions for the given command type and simply calls these actions passing the given command as a parameter.
Hope it helps.
Advanced: you can do one step further: have a ConsumeItem command:
public sealed void ConsumeItem: ICommand {
public InventoryItem Item { get; set; }
}
You already have a class that is responsible for holding a map between InventoryItem and Commands, so this class can become a process manager:
It subscribes to ConsumeItem command (through the bus)
In its Handle method it gets the list of commands for the given inventory item
It sends these commands to the bus.
Well, now we have separated clearly these three concerns:
While consuming an inventory item we just "know" about IBus and send a ConsumeItem command and we don't care what happens next.
The "ConsumeInventoryManager" (whatever you call it) also knows about IBus', subscribes forConsumeItem` command and "knows" what needs to be done when each item is consumed (list of commands). It just sends these commands and doesn't care who and how handle them.
The business logic (characters, monsters, etc) just handle the commands that make sense to them (RestoreHealth, Die, etc) and don't care where (and why) they came from.
Good luck :)
My advice is to use reflection, that is define a method that invokes the desired method based on the specified name. Here's a working example:
class Program
{
static void Main(string[] args)
{
SomeClass someInstance = new SomeClass();
string name = Console.ReadLine();
someInstance.Call("SayHello", name);
}
}
class SomeClass
{
public void SayHello(string name)
{
Console.WriteLine(String.Format("Hello, {0}!", name));
}
public void Call(string methodName, params object[] args)
{
this.GetType().GetMethod(methodName).Invoke(this, args);
}
}
You can do it this way provided the following conditions hold:
You are absolutely sure that a call is possible, that is a method of the specified name exists and the number and types of parameters are correct
The method of the specified name is not overloaded, otherwise You'll get a System.Reflection.AmbiguousMatchException
There exists a superclass from which all of the classes You want to use the Call method on derive; You should define this method in that class
To assure* that conditions 1. and 2. are satisfied You could use a more specific version of Type.GetMethod which takes into account not only the name of the method, but also the number and types of the parameters, and check that there is such a method before invoking it; then the Call method would look like this (*it won't work for methods with parameters marked as out or ref):
public void Call(string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = this.GetType().GetMethod(methodName, argTypes);
//check if the method exists and invoke it
if (method != null)
method.Invoke(this, args);
}
REMARK: MethodInfo.Invoke method actually returns an object, so You could define the Call method to return some value by specifying the return type and using the return keyword together with an appropriate cast or some other method of converting the result to the desired type, if it's possible - remember to check if it is.
If condition 3. isn't satisfied, I'd go with writing an extension method. Here's an example of an extension method that returns a generic value, which I think should be sufficient in most cases (again, it won't work with ref or out) and should work on almost every object possible in the .NET Framework (I'd be grateful for pointing out a counterexample):
public static class Extensions
{
//invoke a method with the specified name and parameter list
// and return a result of type T
public static T Call<T>(this object subject, string methodName, params object[] args)
{
//get the method with the specified name and parameter list
Type[] argTypes = args.Select(arg => arg.GetType()).ToArray();
MethodInfo method = subject.GetType().GetMethod(methodName, argTypes);
//check if the method exists
if (method == null)
return default(T); //or throw an exception
//invoke the method and get the result
object result = method.Invoke(subject, args);
//check if something was returned
if (result == null)
return default(T); //or throw an exception
//check if the result is of the expected type (or derives from it)
if (result.GetType().Equals(typeof(T)) || result.GetType().IsSubclassOf(typeof(T)))
return (T)result;
else
return default(T); //or throw an exception
}
//invoke a void method more conveniently
public static void Call(this object subject, string methodName, params object[] args)
{
//invoke Call<object> method and ignore the result
subject.Call<object>(methodName, args);
}
}
You should then be able to use, for example, someObject.Call<string>("ToString") instead of someObject.ToString(). Finally, at this point I'd strongly recommend:
Use more specific type than object if possible
Use some more sophisticated and unique name than Call - it may get obscured in case some class has a method with the same signature defined
Lookup covariance and contravariance to get more useful knowledge
I'm creating a framework that contains a wrapper around a library (specifically SharpBrake) that performs all interaction with SharpBrake via reflection so there's no hard dependency on the library to 3rd parties of my framework.
If 3rd parties of my framework wants to use SharpBrake, they can just stuff the SharpBrake.dll into the bin folder, but if they don't, they can just forget about it. If my framework had explicit references to SharpBrake types, users of my framework would get exceptions during runtime of SharpBrake.dll missing, which I don't want.
So, my wrapper first loads SharpBrake.dll from disk, finds the AirbrakeClient type, and stores a delegate pointing to the AirbrakeClient.Send(AirbrakeNotice) method in a private field. My problem, however, is that since the Send() method takes an AirbrakeNotice object and I can't reference the AirbrakeNotice object directly, I need to somehow convert the Send() method to an Action<object>.
I have a strong feeling this isn't possible, but I want to explore all options before settling on exposing Delegate and using DynamicInvoke(), which I assume is far from optimal, performance-wise. What I would love to do is the following:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
MethodInfo sendMethod = clientType.GetMethod("Send", new[] { noticeType });
object client = Activator.CreateInstance(clientType);
Type actionType = Expression.GetActionType(noticeType);
Delegate sendMethodDelegate = Delegate.CreateDelegate(actionType, client, sendMethod);
// This fails with an InvalidCastException:
Action<object> sendAction = (Action<object>)sendMethodDelegate;
However, this fails with the following exception:
System.InvalidCastException: Unable to cast object of type 'System.Action`1[SharpBrake.Serialization.AirbrakeNotice]' to type 'System.Action`1[System.Object]'.
Obviously, because sendMethodDelegate is an Action<AirbrakeNotice> and not an Action<object>. Since I can't mention AirbrakeNotice in my code, I'm forced to do this:
Action<object> sendAction = x => sendMethodDelegate.DynamicInvoke(x);
or just exposing the Delegate sendMethodDelegate directly. Is this possible? I know that there's chance of getting into situations where the object can be of a different type than AirbrakeNotice which would be bad, but seeing how much you can mess up with reflection anyway, I'm hoping there's a loophole somewhere.
If you're happy to use expression trees, it's reasonably simple:
ConstantExpression target = Expression.Constant(client, clientType);
ParameterExpression parameter = Expression.Parameter(typeof(object), "x");
Expression converted = Expression.Convert(parameter, noticeType);
Expression call = Expression.Call(target, sendMethod, converted);
Action<object> action = Expression.Lambda<Action<object>>(call, parameter)
.Compile();
I think that's what you want...
If you don't need below C# 4 support you can get much greater performance using the dynamic vs DynamicInvoke.
Action<dynamic> sendAction = x => sendMethodDelegate(x);
Actually I guess you wouldn't even need the above if you can use dynamic, because it would increase performance and simplify everything if you just did:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
dynamic client = Activator.CreateInstance(clientType);
...
client.Send(anAirbrakeNotice);
But if you need to support .net 3.5 jon skeets answer with expression trees is definitely the way to go.
From my comment on the OP:
I'd avoid extended use of reflections if you are concerned about performance. If you can come up with an interface for the class(es) you are using, then I'd create one. Then write a wrapper that implements the interface by calling into the SharpBreak code, and stuff it in a separate DLL. Then dynamically load just your wrapper assembly and concrete wrapper type(s), and call into that interface. Then you don't have to do reflections at a method level.
I'm not sure all the classes you'd need, but here's a simple example of how you can hook into that library with loose coupling based on interfaces.
In your program's assembly:
public IExtensions
{
void SendToAirbrake(Exception exception);
}
public static AirbreakExtensions
{
private static IExtensions _impl;
static()
{
impl = new NullExtensions();
// Todo: Load if available here
}
public static void SendToAirbrake(this Exception exception)
{
_impl.SendToAirbrake(exception);
}
}
internal class NullExtensions : IExtensions // no-op fake
{
void SendToAirbrake(Exception exception)
{
}
}
In a load-if-available (via reflections) assembly
public ExtensionsAdapter : IExtensions
{
void SendToAirbrake(Exception exception)
{
SharpBrake.Extensions.SendToAirbrake(exception);
}
}
The advantage of this approach is that you only use reflections once (on load), and never touch it again. It is also simple to modify to use dependency injection, or mock objects (for testing).
Edit:
For other types it will take a bit more work.
You might need to use the Abstract Factory pattern to instantiate an AirbrakeNoticeBuilder, since you need to deal directly with the interface, and can't put constructors in interfaces.
public interface IAirbrakeNoticeBuilderFactory
{
IAirbrakeNoticeBuilder Create();
IAirbrakeNoticeBuilder Create(AirbrakeConfiguration configuration);
}
If you're dealing with custom Airbreak structures, you'll have even more work.
E.g. for the AirbrakeNoticeBuilder you will have to create duplicate POCO types for any related classes that you use.
public interface IAirbrakeNoticeBuilder
{
AirbrakeNotice Notice(Exception exception);
}
Since you're returning AirbrakeNotice, you might have to pull in nearly every POCO under the Serialization folder, depending on how much you use, and how much you pass back to the framework.
If you decide to copy the POCO code, including the whole object tree, you could look into using AutoMapper to convert to and from your POCO copies.
Alternately, if you don't use the values in the classes you're getting back, and just pass them back to the SharpBreak code, you could come up with some sort of opaque reference scheme that will use a dictionary of your opaque reference type to the actual POCO type. Then you don't have to copy the whole POCO object tree into your code, and you don't need to take as much runtime overhead to map the object trees back and forth:
public class AirbrakeNotice
{
// Note there is no implementation
}
internal class AirbreakNoticeMap
{
static AirbreakNoticeMap()
{
Map = new Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice>();
}
public static Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice> Map { get; }
}
public interface IAirbrakeClient
{
void Send(AirbrakeNotice notice);
// ...
}
internal class AirbrakeClientWrapper : IAirbrakeClient
{
private AirbrakeClient _airbrakeClient;
public void Send(AirbrakeNotice notice)
{
SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice];
_airbrakeClient.Send(actualNotice);
}
// ...
}
internal class AirbrakeNoticeBuilderWrapper : IAirbrakeNoticeBuilder
{
AirbrakeNoticeBuilder _airbrakeNoticeBuilder;
public AirbrakeNotice Notice(Exception exception)
{
SharpBreak.AirbrakeNotice actualNotice =
_airbrakeNoticeBuilder.Notice(exception);
AirbrakeNotice result = new AirbrakeNotice();
AirbreakNoticeMap.Map[result] = actualNotice;
return result;
}
// ...
}
Keep in mind that you only need to wrap the classes and parts of the public interface that you're going to use. The object will still behave the same internally, even if you don't wrap its entire public interface. This might mean you have to do less work, so think hard and try to wrap only what you need now, and what you know you're going to need in the future. Keep YAGNI in mind.
The programming style I have come to really like for problems like this is to write as much strongly-typed code as possible, and then hand off the logic from the dynamically-typed code to the strongly-typed code. So I would write your code like this:
//your code which gets types
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
//construct my helper object
var makeDelegateHelperType=typeof(MakeDelegateHelper<,>).MakeGenericType(clientType, noticeType);
var makeDelegateHelper=(MakeDelegateHelper)Activator.CreateInstance(makeDelegateHelperType);
//now I am in strongly-typed world again
var sendAction=makeDelegateHelper.MakeSendAction();
And this is the definition of the helper object, which is able to get away with fewer reflectiony calls.
public abstract class MakeDelegateHelper {
public abstract Action<object> MakeSendAction();
}
public class MakeDelegateHelper<TClient,TNotice> : MakeDelegateHelper where TClient : new() {
public override Action<object> MakeSendAction() {
var sendMethod = typeof(TClient).GetMethod("Send", new[] { typeof(TNotice) });
var client=new TClient();
var action=(Action<TNotice>)Delegate.CreateDelegate(typeof(Action<TNotice>), client, sendMethod);
return o => action((TNotice)o);
}
}
I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary