I have a unit test:
[Test]
[TestCaseSource(typeof(AllExampleEnumValues))]
public void GivenSth_WhenSth_ThenSth(ExampleEnum enumValue)
{
// Given
var givenState = BaseClassProperty; // property from fixture's base class
systemUnderTest.SetSomeState(givenState);
// When
var result = systemUnderTest.AnswerAQuestion(
"What's the answer to"
+ " the Ultimate Question of Life,"
+ " the Universe,"
+ " and Everything?");
// Then
Assert.That(result, Is.EqualTo(42));
}
where AllExampleEnumValues is as follows:
public class AllGranularities : IEnumerable
{
public IEnumerator GetEnumerator()
{
return Enum
.GetValues(typeof(ExampleEnum))
.Cast<ExampleEnum>()
.Select(ee => new object[] { ee })
.GetEnumerator();
}
}
and in the base class I have:
protected int BaseClassProperty
{
get
{
return //depending on enumValue
}
}
How can I get the current value of enumValue parameter during runtime within the BaseClassProperty, without changing it to a function and passing enumValue as parameter?
I know I could somehow walk the stackframe and read it from there (no, actually, I could not: How can I get the values of the parameters of a calling method?), but perhaps there is a more elegant solution?
I need this to improve tests' readability - the fact that enumValue will influence the result of reading BaseClassProperty implicitly won't reduce readability, because in my domain this dependency is obvious to everyone.
I've been looking into the TextContext class, but it seems it has nothing useful in this context. As mentioned in the comments, the value is present in test's name - however parsing the value from a string is not acceptable here, as sometimes we use multiple parameters, and generic test cases.
Another trail leads to using IApplyToTest attribute. This however would require applying this attribute to every test.
And finally, another trail leads to using ITestAction, from within I have access to the ITest interface, which gives a TestMethod instance. It has the Arguments property! Unfortunately - it's private.
I've managed to create the following workaround:
[AttributeUsage(AttributeTargets.Class)]
public class TrackEnumValueActionAttribute : Attribute, ITestAction
{
public ActionTargets Targets
{
get
{
return ActionTargets.Test;
}
}
public void AfterTest(ITest test)
{
}
public void BeforeTest(ITest test)
{
if (!(test.Fixture is ICurrentExampleEnumValueHolder))
{
return;
}
var arguments = GetArgumentsFromTestMethodOrNull(test);
if (arguments == null)
{
return;
}
var eumValue = GetEnumValueFromArgumentsOrNull<ExampleEnum>(arguments);
(test.Fixture as ICurrentExampleEnumValueHolder).CurrentEnumValue = enumValue;
}
private object[] GetArgumentsFromTestMethodOrNull(ITest test)
{
return test
.GetType()
.GetProperty("Arguments", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
?.GetValue(test) as object[];
}
private T? GetEnumValueFromArgumentsOrNull<T>(object[] arguments) where T : struct
{
return arguments
.Where(a => a.GetType().Equals(typeof(T)))
.Select(a => (T?)a)
.FirstOrDefault();
}
}
Applying this attribute to the base class of my fixture, and implementing the ICurrentExampleEnumValueHolder interface does the trick - the value of my property (present in the interface) has a value that depends on test method call arguments.
Unfortunately, the Arguments property of a TestMethod class in NUnit is internal, hence the ugly reflection workaround. I've posted an issue regarding this matter: https://github.com/nunit/nunit/issues/2079
Related
I wanted one method in mocked object to perfrom its original behavior and return a value by that behavior. But I could not make it.
The below is a sample code.
public interface IMyTest {
public StringBuilder GetBuilder(string initial);
}
public class MyTest : IMyTest {
public StringBuilder GetBuilder(string initial) {
return new StringBuilder(initial + initial);
}
}
[TestFixture]
public class MyTestTest {
[Test]
public void GetBuilderTest() {
Mock<IMyTest> obj = new() {
CallBase = true
};
obj.Setup(x => x.GetBuilder(It.IsAny<string>())).CallBase();
var a = obj.Object.GetBuilder("ABC");
TestContext.WriteLine(a.ToString());
}
}
So I have created a mock object of IMyTest, and wanted let the GetBuilder() method to do the actual original behavior of doubling the input string.
I thought the CallBase() is for such a purpose, but it raises an error like:
This is a DynamicProxy2 error: The interceptor attempted to 'Proceed' for method 'System.Text.StringBuilder GetBuilder(System.String)' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)
Because I am still new to Moq, I might be misunderstanding, but could not find an answer by googling. So if you could kindly help on my question.
Of course, it can use the Return() with the same new StringBuilder(initial + initial) in it, but please think that method is doing very complex work inside of it actually that I do not want to mimic it manually.
A sample code I tried to return an instance of class is given below.
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
How can I mention the class type here since the type is not known at compile time but it will decided at runtime.In the above example i just pass a value 1 (it can be anything and that class will be called accordingly), and the class test1 called.
here I will get an error on the line objcls.callclass(), because objcls is an object instance that doesn't have a callclass()method.
How can I restructure this piece of code? My aim is if I mention a class in the getConstructorclass() method, an object should be returned so as to use it in the further code to invoke the members of that class.
If you know that your classes will have this method, you should use a common interface for them and implement it accordingly. Then you will work with classes that you have made sure it will work.
It would look like this
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
I don't think you should use some generic object returning constructor based on an int variable, if your classes don't have anything in common. It's really weird to handle it like this and it may lead to various problems (some of which you're currently already experiencing). Generic class constructors make sense if the classes are somewhat related and you can predict the outcome, but to create a do-it-all method.. Not so sure about correctness of such approach.
Anyway, if you insist (not recommended, but as you wish), you can create some checks for a type like this:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
But it gets very error prone soon, refactoring will probably be a nightmare etc., but it's your call..
Or you maybe can use solution from pwas, but to me it seems unnecessarily complicated for such a basic task. Looks nice and all, but it still returns only the type "object", so it doesn't really solve your specific problem.
Also, to address one issue I'm not sure you understand - you've already created the instance, you just return type object. That is why you can't call any specific methods on this object, because first you have to cast it to something, that actually has that method and make sure the cast can be done (inheritance etc).
If interface solution (see other answers) is enough, don't look at this answer. When you can't use common base class / interface and you still want call members, you can use solution with is keyword (and check types). Instead of writing many ifs for each case, you can use fluent API:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
Solution:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
Remeber - it would be more elegant to use common interface (as other answers say) - my is only alternative way.
Declare your variable as dynamic
dynamic objcls = getconstrorclass();
Using this the will be determined at run-time, whatever the getconstrorclass method returns. You can access any member of the type and you won't get any error at compile-time. But if you try to access a member which doesn't exists you will get a RuntimeBinderException at runtime.
I would recommend using an interface and restricting the classes that you can instantiate this way to only those that implement the interface.
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
not sure what you want to achieve in the end, but this looks like a job for "Dependency Injection" - here is a nice sample using autofac
Given an enum type:
public enum Work
{
Normal,
Extended
}
What I would like to do is the following.
public abstract class Builder<T>
{
public static Builder<T> GetBuilder<T> (T work)
{
return new Builder<T> ();
}
}
public class BuilderNormal : Builder<Work.Normal>
{
}
public class BuilderExtended : Builder<Work.Extended>
{
}
I specifically want to avoid using a switch/case in Builder or using a mapping that I would need to maintain when I would add a new enum value to Work, i.e. I could do this
public abstract class Builder
{
public static Builder GetBuilder (Work work)
{
switch (work)
{
case Work.Normal:
return new BuilderNormal ();
case Work.Extended:
return new BuilderExtended ();
default:
throw new ...
}
}
}
So, basically, I want to create an instance of a class depending on an enum value and the class must be a child class of an abstract class.
You can't in the way you've designed, basically. Generic type parameters are always for types, not values.
What you can certainly do is maintain a single Dictionary<Work, Func<Builder>> to allow you to basically register factories. That will avoid the switch statement, but it's still somewhere that you could forget to add values.
I'd rely on unit tests to avoid the problem though - write a test which checks that you can create a Builder for every value within the enum; then if you ever add a value to the enum without adding a mapping, your test will fail.
EDIT: Another option would be to add an attribute to the enum values to say which builder type corresponds to that value. You'd then need to extract that type with reflection and instantiate it that way.
You could do something pointless, crazy and slow like
public abstract class Builder
{
public static TBuilder GetBuilder<TBuilder>() where TBuilder : Builder
{
var ctors = typeof(TBuilder).GetConstructors(
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public);
var matchingCtor = ctors.Single(
ci =>
{
var paramInfo = ci.GetParameters();
if (paramInfo.Length != parameters.Length)
{
return false;
}
return !paramInfo.Where((t, i) =>
t.ParameterType != parameters[i].GetType()).Any();
});
return (TBuilder)matchingCtor.Invoke(parameters);
}
}
which would give you a kind of static generic instance constructor, so you could do,
var builderNormal = Builder.GetBuilder<BuilderNormal>();
but, why not just call the instance constructor directly?
I currently have a switch statement that runs around 300 odd lines. I know this is not as giant as it can get, but I'm sure there's a better way to handle this.
The switch statement takes an Enum that is used to determine certain properties that pertain to logging. Right now the problem sets in that it is very easy to leave out an enumeration value and that it will not be given a value as it is not in the switch statement.
Is there an option one can use to ensure that every enumeration is used and given a custom set of values it needs to do its job?
EDIT:
Code sample as requested: (This is simplistic, but shows exactly what I mean. Also an Enumeration would exist with the below values.)
internal void GenerateStatusLog(LogAction ActionToLog)
{
switch (ActionToLog)
{
case LogAction.None:
{
return;
}
case LogAction.LogThis:
{
ActionText = "Logging this Information";
LogText = "Go for it.";
break;
}
}
// .. Do everything else
}
EDIT
I thought this over again, looked around in related questions in SO, and I wrote some code. I created a class named AdvancedSwitch<T>, which allows you to add cases and exposes a method to evaluate a value and lets you specify values that it should check for existence.
This is what I came up with:
public class AdvancedSwitch<T> where T : struct
{
protected Dictionary<T, Action> handlers = new Dictionary<T, Action>();
public void AddHandler(T caseValue, Action action)
{
handlers.Add(caseValue, action);
}
public void RemoveHandler(T caseValue)
{
handlers.Remove(caseValue);
}
public void ExecuteHandler(T actualValue)
{
ExecuteHandler(actualValue, Enumerable.Empty<T>());
}
public void ExecuteHandler(T actualValue, IEnumerable<T> ensureExistence)
{
foreach (var val in ensureExistence)
if (!handlers.ContainsKey(val))
throw new InvalidOperationException("The case " + val.ToString() + " is not handled.");
handlers[actualValue]();
}
}
You can consume the class this way:
public enum TrafficColor { Red, Yellow, Green }
public static void Main()
{
Console.WriteLine("Choose a traffic color: red, yellow, green?");
var color = (TrafficColor)Enum.Parse(typeof(TrafficColor), Console.ReadLine());
var result = string.Empty;
// Creating the "switch"
var mySwitch = new AdvancedSwitch<TrafficColor>();
// Adding a single case
mySwitch.AddHandler(TrafficColor.Green, delegate
{
result = "You may pass.";
});
// Adding multiple cases with the same action
Action redAndYellowDelegate = delegate
{
result = "You may not pass.";
};
mySwitch.AddHandler(TrafficColor.Red, redAndYellowDelegate);
mySwitch.AddHandler(TrafficColor.Yellow, redAndYellowDelegate);
// Evaluating it
mySwitch.ExecuteHandler(color, (TrafficColor[])Enum.GetValues(typeof(TrafficColor)));
Console.WriteLine(result);
}
With the creative use of anonymous delegates, you can easily add new cases to your "switch block". :)
Not that you can also use lambda expressions, and lambda blocks, eg () => { ... } instead of delegate { ... }.
You can easily use this class instead of the long switch blocks.
Original post:
If you use Visual Studio, always create swich statements with the switch code snippet. Type switch press tab twice, and it auto-generates all the possibilities for you.
Then, add a default case to the end which throws an exception, that way when testing your app you will notice that there is an unhandled case, instantly.
I mean something like this:
switch (something)
{
...
case YourEnum.SomeValue:
...
break;
default:
throw new InvalidOperationException("Default case reached.");
}
Well, there's throwing in the default case... There's no edit / compile time construct other than that.
However Strategy, Visitor and other patterns related to them may be appropriate if you choose to do it at run time.
Sample code will help with getting the best answer.
EDIT: Thanks for the sample. I still think it needs a bit of fleshing out as you dont cover whether there are some parameters that only apply to some cases etc.
Action is often used as an alias for the Command pattern and the fact that your Enum is called LogAction signifies that each value carries with it a behavior - be that implied (you stick appropriate code in a case) or explicit (in the specific Command hierarchy class).
Thus it looks to me like a usage of the Command pattern is appropriate (though your sample doesnt prove it) - i.e., have a class (potentially a hierarchy using constructor overloads or any other [set of] factory mechanisms) that keeps the state associated with the request along with the specific behaviour. Then, instead of passing an Enum value, create an appropriate LogCommand instance to the logger, which just invokes it (potentially passing a Log Sink 'receptacle' which the Command can log into). Otherwise you're poking random subsets of parameters in different places.
SEEALSO related posts:
C# - Is there a better alternative than this to ‘switch on type’?
Replace giant switch statement with what?
One possible solution is to use a SortedDictionary:
delegate void EnumHandler (args);
SortedDictionary <Enum, EnumHandler> handlers;
constructor
{
handlers = new SortedDictionary <Enum, EnumHandler> ();
fill in handlers
}
void SomeFunction (Enum enum)
{
EnumHandler handler;
if (handlers.TryGetValue (enum, out handler))
{
handler (args);
}
else
{
// not handled, report an error
}
}
This method does allow you to replace the handlers dynamically. You could also use a List as the value part of the dictionary and have multiple handlers for each enum.
Try to use reflection.
Decorate enum options with attributes that holds associated value and return this value.
Create static class of constants and use reflection for mapping enum-option to constant by name
hope this will help
Some times storing the options in a map is a good solution, you can externalize the configuration to a file too, not sure if it applies to your application.
Long code example here, and the final generic code is a little heavy (EDIT have added an extra example that eliminates the need for the angle brackets at the expense of some final flexibility).
One thing that this solution will give you is good performance - not quite as good as a straightforward switch statement, but each case statement becomes a dictionary lookup and method invocation, so still pretty good. The first call will get a performance penalty, however, due to the use of a static generic that reflects on initialisation.
Create an attribute and generic type as follows:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DynamicSwitchAttribute : Attribute
{
public DynamicSwitchAttribute(Type enumType, params object[] targets)
{ Targets = new HashSet<object>(targets); EnumType = enumType; }
public Type EnumType { get; private set; }
public HashSet<object> Targets { get; private set; }
}
//this builds a cache of methods for a given TTarget type, with a
//signature equal to TAction,
//keyed by values of the type TEnum. All methods are expected to
//be instance methods.
//this code can easily be modified to support static methods instead.
//what would be nice here is if we could enforce a generic constraint
//on TAction : Delegate, but we can't.
public static class DynamicSwitch<TTarget, TEnum, TAction>
{
//our lookup of actions against enum values.
//note: no lock is required on this as it is built when the static
//class is initialised.
private static Dictionary<TEnum, TAction> _actions =
new Dictionary<TEnum, TAction>();
private static MethodInfo _tActionMethod;
private static MethodInfo TActionMethod
{
get
{
if (_tActionMethod == null)
{
//one criticism of this approach might be that validation exceptions
//will be thrown inside a TypeInitializationException.
_tActionMethod = typeof(TAction).GetMethod("Invoke",
BindingFlags.Instance | BindingFlags.Public);
if (_tActionMethod == null)
throw new ArgumentException(/*elided*/);
//verify that the first parameter type is compatible with our
//TTarget type.
var methodParams = _tActionMethod.GetParameters();
if (methodParams.Length == 0)
throw new ArgumentException(/*elided*/);
//now check that the first parameter is compatible with our type TTarget
if (!methodParams[0].ParameterType.IsAssignableFrom(typeof(TTarget)))
throw new ArgumentException(/*elided*/);
}
return _tActionMethod;
}
}
static DynamicSwitch()
{
//examine the type TTarget to extract all public instance methods
//(you can change this to private instance if need be) which have a
//DynamicSwitchAttribute defined.
//we then project the attributes and the method into an anonymous type
var possibleMatchingMethods =
from method in typeof(TTarget).
GetMethods(BindingFlags.Public | BindingFlags.Instance)
let attributes = method.GetCustomAttributes(
typeof(DynamicSwitchAttribute), true).
Cast<DynamicSwitchAttribute>().ToArray()
where attributes!= null && attributes.Length == 1
&& attributes[0].EnumType.Equals(typeof(TEnum))
select new { Method = method, Attribute = attributes[0] };
//create linq expression parameter expressions for each of the
//delegate type's parameters
//these can be re-used for each of the dynamic methods we generate.
ParameterExpression[] paramExprs = TActionMethod.GetParameters().
Select((pinfo, index) =>
Expression.Parameter(
pinfo.ParameterType, pinfo.Name ?? string.Format("arg{0}"))
).ToArray();
//pre-build an array of these parameter expressions that only
//include the actual parameters
//for the method, and not the 'this' parameter.
ParameterExpression[] realParamExprs = paramExprs.Skip(1).ToArray();
//this has to be generated for each target method.
MethodCallExpression methodCall = null;
foreach (var match in possibleMatchingMethods)
{
if (!MethodMatchesAction(match.Method))
continue;
//right, now we're going to use System.Linq.Expressions to build
//a dynamic expression to invoke this method given an instance of TTarget.
methodCall =
Expression.Call(
Expression.Convert(
paramExprs[0], typeof(TTarget)
),
match.Method, realParamExprs);
TAction dynamicDelegate = Expression.
Lambda<TAction>(methodCall, paramExprs).Compile();
//now we have our method, we simply inject it into the dictionary, using
//all the unique TEnum values (from the attribute) as the keys
foreach (var enumValue in match.Attribute.Targets.OfType<TEnum>())
{
if (_actions.ContainsKey(enumValue))
throw new InvalidOperationException(/*elided*/);
_actions[enumValue] = dynamicDelegate;
}
}
}
private static bool MethodMatchesAction(MethodInfo method)
{
//so we want to check that the target method matches our desired
//delegate type (TAction).
//The way this is done is to fetch the delegate type's Invoke
//method (implicitly invoked when you invoke delegate(args)), and
//then we check the return type and parameters types of that
//against the return type and args of the method we've been passed.
//if the target method's return type is equal to or derived from the
//expected delegate's return type, then all is good.
if (!_tActionMethod.ReturnType.IsAssignableFrom(method.ReturnType))
return false;
//now, the parameter lists of the method will not be equal in length,
//as our delegate explicitly includes the 'this' parameter, whereas
//instance methods do not.
var methodParams = method.GetParameters();
var delegateParams = TActionMethod.GetParameters();
for (int i = 0; i < methodParams.Length; i++)
{
if (!methodParams[i].ParameterType.IsAssignableFrom(
delegateParams[i + 1].ParameterType))
return false;
}
return true;
}
public static TAction Resolve(TEnum value)
{
TAction result;
if (!_actions.TryGetValue(value, out result))
throw new ArgumentException("The value is not mapped");
return result;
}
}
Now do this in a Unit Test:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(1,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.BlahBlah)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Blip)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Bop)(this));
}
public enum Blah
{
BlahBlah,
Bloo,
Blip,
Bup,
Bop
}
[DynamicSwitchAttribute(typeof(Blah), Blah.BlahBlah)]
public int Method()
{
return 1;
}
[DynamicSwitchAttribute(typeof(Blah), Blah.Blip, Blah.Bop)]
public int Method2()
{
return 125;
}
So, given a value of TEnum, and your preferred 'action' type (in your code you would appear to be simply returning nothing and modifying the internal state of the class), you simply consult the DynamicSwitch<> class, ask it to resolve a target method, and then invoke it inline (passing the target object on which the method will be invoked as the first parameter).
I'm not really expecting any votes for this - it's a MAD solution to be honest (it does have the advantage of being able to be applied for any enum type, and even discreet values of type int/float/double, as well as supporting any delegate type) - so perhaps it's a bit of a sledgehammer!
EDIT
Once you have a static generic like this, angle-bracket hell ensues - so we want to try and get rid of them. A lot of the time, this is done by type inference on method parameters etc - but we have a problem here that we can't easily infer a delegate's signature without repeating the method call i.e. (args) => return.
However, you seem to require a method that takes no parameters and returns void, so you can close over this behemoth generic by fixing the delegate type to Action, and throw a fluid API into the mix as well (if that's your kind of thing):
public static class ActionSwitch
{
public class SwitchOn<TEnum>
{
private TEnum Value { get; set; }
internal SwitchOn(TEnum value)
{
Value = value;
}
public class Call<TTarget>{
private TEnum Value { get; set; }
private TTarget Target { get; set; }
internal Call(TEnum value, TTarget target)
{
Value = value;
Target = target;
Invoke();
}
internal void Invoke(){
DynamicSwitch<TTarget, TEnum, Action<TTarget>>.Resolve(Value)(Target);
}
}
public Call<TTarget> On<TTarget>(TTarget target)
{
return new Call<TTarget>(Value, target);
}
}
public static SwitchOn<TEnum> Switch<TEnum>(TEnum onValue)
{
return new SwitchOn<TEnum>(onValue);
}
}
Now add this to the test project:
[TestMethod]
public void TestMethod2()
{
//no longer have any angle brackets
ActionSwitch.Switch(Blah.Bup).On(this);
Assert.IsTrue(_actionMethod1Called);
}
private bool _actionMethod1Called;
[DynamicSwitch(typeof(Blah), Blah.Bup)]
public void ActionMethod1()
{
_actionMethod1Called = true;
}
Only issue with this (apart from the complexity of the solution :) ) is that you'd have to re-build this static wrapper type whenever you want to use a new type of target delegate for a dynamic switch elsewhere. You could generate a generic version based on the Action<...> and Func<...> delegates that incorporates TArg1, TArg(n) and TReturn (if Func<>) - but you'd end up writing a lot more code.
Perhaps I'll turn this into an article on my blog and do all of that - if I get the time!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding the Variable Name passed to a Function in C#
In C#, is there a way (terser the better) to resolve the name of a parameter at runtime?
For example, in the following method, if you renamed the method parameter, you'd also have to remember to update the string literal passed to ArgumentNullException.
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException("resource");
}
// ..
}
One way:
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
This code also requires a supporting function:
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
Basically the code works by defining a new Anonymous Type with a single Property consisting of the parameter who's name you want. GetName() then uses reflection to extract the name of that Property.
There are more details here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
Short answer: No, there isn't. (Is that terse enough? ;)
(EDIT: Justin's answer probably counts. It leaves a bad taste in my mouth, but it accomplishes the goal of "no need to put the parameter name into a string". I don't think I'd really count AOP though, as that's really changing to a completely different approach rather than answering the original question of getting a parameter name from within a method.)
Longer answer: There's a way to find out all the parameters of a method, but I don't think it's useful in this case.
Here's an example which displays the parameter names from a couple of methods:
using System;
using System.Reflection;
class Test
{
static void Main()
{
Foo(null);
Bar(null);
}
static void Foo(object resource)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void Bar(object other)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void PrintParameters(MethodBase method)
{
Console.WriteLine("{0}:", method.Name);
foreach (ParameterInfo parameter in method.GetParameters())
{
Console.WriteLine(" {0} {1}",
parameter.ParameterType,
parameter.Name);
}
}
}
So that does that, but if you have multiple parameters and you wanted to throw an appropriate exception, how would you know (in a safe way) which to use? Ideally you want something like:
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException(infoof(resource));
}
// ..
}
where the mythical infoof operator would return a ParameterInfo. Unfortunately this doesn't exist.
I dealt with this very same issue. There are a couple of ways of getting the parameter name but the most performant is to dip down into the IL. You can see an example of my implementation on my blog post on this very issue Taking the pain out of parameter validation.
The one caveat to this approach is you need to pass the parameter name in as a delegate but it is small price to pay for cleaner code:
public void SomeMethod(string value)
{
Validate.Argument(() => value).IsNotNull().IsNotEmpty();
}
Which is somewhat cleaner and clearer than:
public void SomeMethod(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value == string.Empty)
{
throw new ArgumentException("Value cannot be an empty string.", "value");
}
}
The static method approach has allowed me to chain a number of methods together in a fluent interface. Initially an Argument object is returned which only allows a basic null test which returns a ReferenceArgument object which can then have additional validation. If the object under test is a value type then different tests are available.
The API allows for a number of common tests but it would be hard to capture all the possible tests so to provide flexibility a generic test method allows an expression or function to be provided and in the case of the former the expression can actually be used as the error message.
My example only covers a few of the basics but you can easily expand the interface to check for ranges and throw ArgumentOutOfRangeExceptions or test objects inherit from a specific base class or implement an interface. There are some similar implementations but I have not as yet seen any that get the parameter name.
You can get this information using AOP. You can define an intercept that is invoked before method execution and throw the exception there. This also takes care of the problem that null checking is a cross-cutting concern.
PostSharp is a good simple implementation of AOP.
Here's what your code would look like (haven't tested, but it should get you very close)
[AttributeUsage(AttributeTargets.Parameter)]
public class CanBeNullAttribute : Attribute
{
private readonly bool canBeNull;
public CanBeNullAttribute()
: this(true)
{
}
public CanBeNullAttribute(bool canBeNull)
{
this.canBeNull = canBeNull;
}
public bool AllowNull
{
get { return canBeNull; }
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class EnforceNullConstraintAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
object[] arguments = eventArgs.GetArgumentArray();
ParameterInfo[] parameters = eventArgs.Delegate.Method.GetParameters();
for (int i = 0; i < arguments.Length; i++)
{
if (arguments[i] != null) continue;
foreach (CanBeNullAttribute attribute in parameters[i].GetCustomAttributes(typeof(CanBeNullAttribute), true))
{
if (!attribute.AllowNull) throw new ArgumentNullException(parameters[i].Name);
}
}
base.OnInvocation(eventArgs);
}
}
Now, you can modify your method:
[EnforceNullConstraint]
public void Woof([CanBeNull(false)] object resource)
{
// no need to check for null, PostSharp will weave it at compile time
// execute logic assured that "resource" is not null
}
You might want:
1)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null || expr.Compile()() != null) //the compile part is slow
return;
throw new ArgumentNullException(((MemberExpression)expr.Body).Member.Name);
}
or
2)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null)
return;
var param = (MemberExpression)expr.Body;
if (((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value) == null)
throw new ArgumentNullException(param.Member.Name);
}
And call it:
Class.ThrowIfNull(() => resource);
But that's not what you would want probably. Its also a lot slower 1) is abt 1000 times slower than 2). May be:
3)
public static void ThrowIfNull<T>(this T item) where T : class
{
if (item == null)
return;
var param = typeof(T).GetProperties()[0];
if (param.GetValue(item, null) == null)
throw new ArgumentNullException(param.Name);
}
And call it:
new { resource }.ThrowIfNull();
Cleaner, much faster than above 2! :)
You can also extend these methods for properties of objects. For eg.,
new { myClass.MyProperty1 }.ThrowIfNull();
You can cache property values to improve performance further as property names don't change during runtime. See related question Finding the variable name passed to a function