How to call a C# method only if it exists? - c#

Is this possible without reflection otherwise with reflection ? This is something very often used in PHP like in Wordpress.
Something in pseudo code:
if (exists(object.method)) {object.method}
or
try {object.method} finally {...}

Well, you could declare it in an interface, and then use:
IFoo foo = bar as IFoo;
if (foo != null)
{
foo.MethodInInterface();
}
That assumes you can make the object's actual type implement the interface though.
Otherwise you'd need to use reflection AFAIK.
(EDIT: The dynamic typing mentioned elsewhere would work on .NET 4 too, of course... but catching an exception for this is pretty nasty IMO.)

You could use dynamics and catch the Runtime exception:
dynamic d = 5;
try
{
Console.WriteLine(d.FakeMethod(4));
}
catch(RuntimeBinderException)
{
Console.WriteLine("Method doesn't exist");
}
Although it sounds more like a design problem.
Disclaimer
This code is not for use, just an example that it can be done.

Use .GetType().GetMethod() to check if it exists, and then .Invoke() it.
var fooBar = new FooBarClass();
var method = fooBar.GetType().GetMethod("ExistingOrNonExistingMethod");
if (method != null)
{
method.Invoke(fooBar, new object[0]);
}

With the dynamic type in C# 4.0, you could do something like this:
dynamic obj = GetDynamicObject();
if (obj != null && obj.GetType().GetMethod("DoSomething") != null)
{
obj.DoSomething();
}
But the only way to tell if a type has a method in the first place is to use reflection; so the above approach doesn't really buy you anything (you might as well take the MethodInfo you get from calling GetMethod and just Invoke it).
Edit: If you're open to trying to call the method even when it's not there, then Yuriy's answer is probably what you're looking for. My original answer was a literal response to the way you worded your question: "How to call a C# method only if it exists."

I came across this looking for the same answer but did not like any of the solutions.
here is mine:
//Invoke the refresh method if the datasource contains it
if (this.DataSource.GetType().GetMethod("Refresh") != null)
this.DataSource.GetType().GetMethod("Refresh").Invoke(this.DataSource, new object[] { });

You should revise existance first. MethodInfo[] myArrayMethodInfo = myType.GetMethods();

Related

C# null-conditional shorthand for method arguments

The null-conditional operator is very useful when the method belongs to the object in question, but what if the object in question is an argument? For example, can this be shortened?
var someList = new List<SomeType>();
if (anotherList.Find(somePredicate) != null)
{
someList.Add(anotherList.Find(somePredicate))
}
One solution I thought of was to use an extension method like below:
public static void AddTo<T>(this T item, List<T> list)
{
list.Add(item);
}
With that the first code block can be reduced to:
var someList = new List<SomeType>();
anotherList.Find(somePredicate)?.AddTo(someList);
But this solution is specific to this example (i.e. adding an object to a list if it's not null). Is there a general way to indicate that if a parameter is null, the method should not be run?
Never do this
var someList = new List<SomeType>();
if (anotherList.Find(somePredicate) != null)
{
someList.Add(anotherList.Find(somePredicate))
}
this will search the list twice which is unnecessary. use a temporary variable instead.
var someList = new List<SomeType>();
var find = anotherList.Find(somePredicate);
if (find != null) someList.Add(find);
Is there a general way to indicate that if a parameter is null, the method should not be run?
Currently there is no such feature. how ever there are other alternatives that work better like in other answers provided.
You could also use just:
var someList = new List<SomeType>();
someList.AddRange(anotherList.Where(somePredicate));
In your case you probably need to make sure that your predicate only finds at max one element.
TLDR: Not yet.
The team plans to implement a functionality into the language, that would do this exact thing. It would look something like this:
someList.Add(anotherList.Find(somePredicate) ?? return);
In which the ?? return checks whether the first argument is null, and if it is, than it returns. (Or you could write break if that is what you want)
I am not sure if this is a thing they are working on at the moment, and if it will be included in the next version of C#, but would go a long way if it is going to be.

Creating an object via lambda factory vs direct "new Type()" syntax

For example, consider a utility class SerializableList:
public class SerializableList : List<ISerializable>
{
public T Add<T>(T item) where T : ISerializable
{
base.Add(item);
return item;
}
public T Add<T>(Func<T> factory) where T : ISerializable
{
var item = factory();
base.Add(item);
return item;
}
}
Usually I'd use it like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(new Class1());
var item2 = serializableList.Add(new Class2());
I could also have used it via factoring, like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(() => new Class1());
var item2 = serializableList.Add(() => new Class2());
The second approach appears to be a preferred usage pattern, as I've been lately noticing on SO. Is it really so (and why, if yes) or is it just a matter of taste?
Given your example, the factory method is silly. Unless the callee requires the ability to control the point of instantiation, instantiate multiple instances, or lazy evaluation, it's just useless overhead.
The compiler will not be able to optimize out delegate creation.
To reference the examples of using the factory syntax that you gave in comments on the question. Both examples are trying (albeit poorly) to provide guaranteed cleanup of the instances.
If you consider a using statement:
using (var x = new Something()) { }
The naive implementation would be:
var x = new Something();
try
{
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
The problem with this code is that it is possible for an exception to occur after the assignment of x, but before the try block is entered. If this happens, x will not be properly disposed, because the finally block will not execute. To deal with this, the code for a using statement will actually be something more like:
Something x = null;
try
{
x = new Something();
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
Both of the examples that you reference using factory parameters are attempting to deal with this same issue. Passing a factory allows for the instance to be instantiated within the guarded block. Passing the instance directly allows for the possibility of something to go wrong along the way and not have Dispose() called.
In those cases, passing the factory parameter makes sense.
Caching
In the example you have provided it does not make sense as others have pointed out. Instead I will give you another example,
public class MyClass{
public MyClass(string file){
// load a huge file
// do lots of computing...
// then store results...
}
}
private ConcurrentDictionary<string,MyClass> Cache = new ....
public MyClass GetCachedItem(string key){
return Cache.GetOrAdd(key, k => new MyClass(key));
}
In above example, let's say we are loading a big file and we are calculating something and we are interested in end result of that calculation. To speedup my access, when I try to load files through Cache, Cache will return me cached entry if it has it, only when cache does not find the item, it will call the Factory method, and create new instance of MyClass.
So you are reading files many times, but you are only creating instance of class that holds data just once. This pattern is only useful for caching purpose.
But if you are not caching, and every iteration requires to call new operator, then it makes no sense to use factory pattern at all.
Alternate Error Object or Error Logging
For some reason, if creation fails, List can create an error object, for example,
T defaultObject = ....
public T Add<T>(Func<T> factory) where T : ISerializable
{
T item;
try{
item = factory();
}catch(ex){
Log(ex);
item = defaultObject;
}
base.Add(item);
return item;
}
In this example, you can monitor factory if it generates an exception while creating new object, and when that happens, you Log the error, and return something else and keep some default value in list. I don't know what will be practical use of this, but Error Logging sounds better candidate here.
No, there's no general preference of passing the factory instead of the value. However, in very particular situations, you will prefer to pass the factory method instead of the value.
Think about it:
What's the difference between passing the parameter as a value, or
passing it as a factory method (e.g. using Func<T>)?
Answer is simple: order of execution.
In the first case, you need to pass the value, so you must obtain it before calling the target method.
In the second case, you can postpone the value creation/calculation/obtaining till it's needed by the target method.
Why would you want to postpone the value creation/calculation/obtaining? obvious things come to mind:
Processor-intensive or memory-intensive creation of the value, that you want to happen only in case the value is really needed (on-demand). This is Lazy loading then.
If the value creation depends on parameters that are accessible by the target method but not from outside of it. So, you would pass Func<T, T> instead of Func<T>.
The question compares methods with different purposes. The second one should be named CreateAndAdd<T>(Func<T> factory).
So depending what functionality is required, should be used one or another method.

How to determine the type of the returned value within the generic method

We've created a generic method like so:
public TReturnType GetValue(string key)
{
var configurationParameter = (from cp in _repository.ConfigurationParameters
where cp.ConfigurationParameterKey == key
select cp).FirstOrDefault();
var returnValue (TReturnType)Convert.ChangeType(configurationParameter.ConfigurationParameterValue, typeof (TReturnType));
return returnValue;
}
Now, we would like to put some error handling in this method so that in case we're expecting a numeric type we can do, for example, an int.TryParse(returnValue, out myNewInt). Of course to be able to do that we would have to be able to determine the type of TReturnType within the method.
Is there a way to do this?
Thanks for all of your help.
Regards.
Sure, but you should consider whether or not this is a good idea. You can always say
if (typeof(T) == typeof(int)) whatever
But doing so is a bit of a bad code smell. The whole point of generics is to be generic. If you have special-purpose code for when T is an integer, then why not simply add another method that handles exactly the integer case?
Sure, just add in some code like this:
if(typeof(TReturnType) == typeof(int))
{
var number = (int)returnValue;
//Validate your output
}

PropertyInfo.GetValue(null, null) returns null

i have a class with a static public property called "Info".
via reflection i want to get this properties value, so i call:
PropertyInfo pi myType.GetProperty("Info");
string info = (string) pi.GetValue(null, null);
this works fine as long as the property is of type string. but actually my property is of type IPluginInfo and a PluginInfo type (implementing IPluginInfo) is instatiated and returned in the Info properties get accessor, like this:
public static IPluginInfo PluginInfo
{
get
{
IPluginInfo Info = new PluginInfo();
Info.Name = "PluginName";
Info.Version = "PluginVersion";
return Info;
}
}
like this when i call:
IPluginInfo info = pi.GetValue(null, null) as IPluginInfo;
info is always null, whiel PropertyInfo pi is still valid. am i missing something obvious here?
Could you create a short but complete program that demonstrates the problem?
Given that you're talking about plugins, my guess is that you've got the problem of having IPluginInfo defined in two different assemblies. See if this article helps at all.
The easiest way to verify it is to call pi.GetValue and store the result in an object variable first, then do the cast or "as" in another line. That way you can break the debugger and look at the return value before it's lost.
My first guess would be that you have re-declared the IPluginInfo interface. All .NET types are scoped by their assembly; if you have the same class file in 2 assemblies, you have 2 different interfaces that happen to have the same name.
ok, thanks for all the answers.
i indeed already had the plugininterface in a separate .dll but had placed this .dll in the pluginhosts directory as well as in the directory with all the plugins.
Um, first of all I'd implement that property a little differently:
private static PluginInfo _PluginInfo = null;
public static IPluginInfo PluginInfo
{
get
{
if (_PluginInfo == null)
{
_PluginInfo = new PluginInfo();
_PluginInfo.Name = "PluginName";
_PluginInfo.Version = "PluginVersion";
}
return _PluginInfo;
}
}
Note that this needs a little more work because it isn't threadsafe, but hopefully you get the idea: build it one time rather than repeatedly.
I'll stop here now, since it looks like two others already finished the rest of my answer while putting together the first part.
In C#, AS returns null if the value does not match the type.
If you write:
object info = pi.GetValue(null, null);
Console.WriteLine(info.GetType().ToString());
what type do you receive?

Finding controls that use a certain interface in ASP.NET

Having a heckuva time with this one, though I feel I'm missing something obvious. I have a control that inherits from System.Web.UI.WebControls.Button, and then implements an interface that I have set up. So think...
public class Button : System.Web.UI.WebControls.Button, IMyButtonInterface { ... }
In the codebehind of a page, I'd like to find all instances of this button from the ASPX. Because I don't really know what the type is going to be, just the interface it implements, that's all I have to go on when looping through the control tree. Thing is, I've never had to determine if an object uses an interface versus just testing its type. How can I loop through the control tree and yank anything that implements IMyButtonInterface in a clean way (Linq would be fine)?
Again, know it's something obvious, but just now started using interfaces heavily and I can't seem to focus my Google results enough to figure it out :)
Edit: GetType() returns the actual class, but doesn't return the interface, so I can't test on that (e.g., it'd return "MyNamespace.Button" instead of "IMyButtonInterface"). In trying to use "as" or "is" in a recursive function, the type parameter doesn't even get recognized within the function! It's rather bizarre. So
if(ctrl.GetType() == typeToFind) //ok
if(ctrl is typeToFind) //typeToFind isn't recognized! eh?
Definitely scratching my head over this one.
Longhorn213 almost has the right answer, but as as Sean Chambers and bdukes say, you should use
ctrl is IInterfaceToFind
instead of
ctrl.GetType() == aTypeVariable
The reason why is that if you use .GetType() you will get the true type of an object, not necessarily what it can also be cast to in its inheritance/Interface implementation chain. Also, .GetType() will never return an abstract type/interface since you can't new up an abstract type or interface. GetType() returns concrete types only.
The reason this doesn't work
if(ctrl is typeToFind)
Is because the type of the variable typeToFind is actually System.RuntimeType, not the type you've set its value to. Example, if you set a string's value to "foo", its type is still string not "foo". I hope that makes sense. It's very easy to get confused when working with types. I'm chronically confused when working with them.
The most import thing to note about longhorn213's answer is that you have to use recursion or you may miss some of the controls on the page.
Although we have a working solution here, I too would love to see if there is a more succinct way to do this with LINQ.
You can just search on the Interface. This also uses recursion if the control has child controls, i.e. the button is in a panel.
private List<Control> FindControlsByType(ControlCollection controls, Type typeToFind)
{
List<Control> foundList = new List<Control>();
foreach (Control ctrl in this.Page.Controls)
{
if (ctrl.GetType() == typeToFind)
{
// Do whatever with interface
foundList.Add(ctrl);
}
// Check if the Control has Child Controls and use Recursion
// to keep checking them
if (ctrl.HasControls())
{
// Call Function to
List<Control> childList = FindControlsByType(ctrl.Controls, typeToFind);
foundList.AddRange(childList);
}
}
return foundList;
}
// Pass it this way
FindControlsByType(Page.Controls, typeof(IYourInterface));
I'd make the following changes to Longhorn213's example to clean this up a bit:
private List<T> FindControlsByType<T>(ControlCollection controls )
{
List<T> foundList = new List<T>();
foreach (Control ctrl in this.Page.Controls)
{
if (ctrl as T != null )
{
// Do whatever with interface
foundList.Add(ctrl as T);
}
// Check if the Control has Child Controls and use Recursion
// to keep checking them
if (ctrl.HasControls())
{
// Call Function to
List<T> childList = FindControlsByType<T>( ctrl.Controls );
foundList.AddRange( childList );
}
}
return foundList;
}
// Pass it this way
FindControlsByType<IYourInterface>( Page.Controls );
This way you get back a list of objects of the desired type that don't require another cast to use. I also made the required change to the "as" operator that the others pointed out.
Interfaces are close enough to types that it should feel about the same. I'd use the as operator.
foreach (Control c in this.Page.Controls) {
IMyButtonInterface myButton = c as IMyButtonInterface;
if (myButton != null) {
// do something
}
}
You can also test using the is operator, depending on your need.
if (c is IMyButtonInterface) {
...
}
Would the "is" operator work?
if (myControl is ISomeInterface)
{
// do something
}
If you're going to do some work on it if it is of that type, then TryCast is what I'd use.
Dim c as IInterface = TryCast(obj, IInterface)
If c IsNot Nothing
'do work
End if
you can always just use the as cast:
c as IMyButtonInterface;
if (c != null)
{
// c is an IMyButtonInterface
}

Categories

Resources