Finding all classes containing a method in C# - c#

I want to search through all classes in a namespace for those containing a certain method. If a class contains a method then I want to create an instance of the class and run the method.
Obviously I have to start with reflection but I'm stuck on where to go.
Edit:
Interfaces are not the way I want to do this.
What I'm looking for is embedding testing functions into the code but a single calling interface. If there's a self-test function, call it. If there isn't, ignore it.

Create an interface that declares the method and then have various classes implement that interface.
You can then use reflection to find all types within an assembly that implement that interface.
From there you'll need to create an instance of each type and then call the method. The implementation details will vary depending on what you are trying to do.
Update based on comments:
I still think an interface (or attribute) is the way to go. This is how it would work with an interface.
interface ISelfTester
{
void SelfTest();
}
class SomeClass : ISelfTester
{
/* ... */
public void SelfTest()
{
// test code
}
/* ... */
}
You could then invoke each type's SelfTest method like so (borrowing from Dathan and Darren Kopp):
var type = typeof(ISelfTester);
var types = AppDomain.CurrentDomain.GetAssemblies()
.Select(x => x.GetTypes())
.SelectMany(x => x)
.Where(x => x.Namespace == "My.Name.Space" && type.IsAssignableFrom(x));
foreach (Type t in types)
{
ISelfTester obj = Activator.CreateInstance(t) as ISelfTester;
obj.SelfTest();
}

Without more information about what distinguishes the method, I'm just going to assume it's distinguished by name, and it's public. The name assumption is dangerous, so I wouldn't recommend doing this, but the following should do what you want (assuming Activator is able to create an instance).
EDIT: Added Where(x => x.Namespace == "My.Name.Space") to limit the results to a single target namespace.
EDIT: Added if ... else to handle the case of static methods.
var methods = AppDomain.CurrentDomain.GetAssemblies()
.Select(x => x.GetTypes())
.SelectMany(x => x)
.Where(x => x.Namespace == "My.Name.Space")
.Where(c => c.GetMethod("MethodName") != null)
.Select(c => c.GetMethod("MethodName"));
foreach (MethodInfo mi in methods)
{
if (mi.IsStatic)
{
mi.Invoke(null, null); // replace null with the appropriate arguments
}
else if (!mi.DeclaringType.IsAbstract)
{
var obj = Activator.CreateInstance(mi.DeclaringType);
mi.Invoke(obj, null); // replace null with the appropriate arguments
}
}
If you have control over the types, though, jrummel's suggestion about interfaces is a much safer way to do this.

One option would be to use Reflection, as described above, but rather than finding the method by name, look for a method tagged with an appropriate custom attribute. This is similar to what the MS DataContractSerializer does with attributes like [OnDeserializing]. This way the class implementer is specifically spelling out their intent for the method, rather than having it suddenly do something unexpected as a result of it having a particular name.
On a side note, since what you're after is a test method, you might check out something like NUnit. There are several excellent free unit testing frameworks out there. They also provide additional features that can help with your testing, as they provide the scaffolding for the different types of test assertions you might want to make.

Related

How to avoid or UnitTest the accidental use of a concrete singleton type instead of its abstraction with StructureMap

I recently had the following bug in my code which took me for ever to debug. I wanted to inject an instance based on its interface like this:
MovementController(IMotorController motorController)
However I accidentally used the concrete type like this:
MovementController(MotorController motorController)
The project still built and ran fine until I tried to access the motorController from the MovementController instance. Since the underlying implementation of IMotorController accesses hardware, it has to be a singleton or my locks code. However, since I had other classes with the injected IMotorController, I now had two instances MotorController in my object-graph, which both accessed the hardware over a serial connection. This caused an error, at run time at a much lower level, which took me forever to debug and find the true cause.
How can I avoid this type of bug or write a unit test for my StructureMap registry to catch this subtle bug?
You could easily check for this using a static analysis tool like NDepend. With it you would just look for types that were controllers and then inspect their constructors and warn if you found any constructor parameters that were not interface types.
Just to refine the Steve answer, you could write a code rule that could look like: (with NDepend a code rule is a C# LINQ query prefixed with warnif count > 0)
// <Name>Don't use MotorController, use IMotorController instead</Name>
warnif count > 0
from m in Application.Methods
where m.IsUsing ("NamespaceA.MotorController ") &&
m.ParentType.FullName != "NamespaceB.ClassThatCanUseMotorController "
select m
The rule can be refined easily if there are zero or many ClassThatCanUseMotorController.
The safest solution is to check during runtime that only one instance of MotorController is created. For instance you could count the number of instances of MotorController with a static counter variable:
public class MotorController : IMotorController
{
private static bool instantiated;
public MotorController(...)
{
if (instantiated)
throw new InvalidOperationException(
"MotorController can only be instantiated once.")
...
instantiated = true;
}
...
}
I'd usually consider this bad design, because whether a class is used as a singleton or not is something only the dependency injection framework should care about. Also note that this is not thread-safe.
Ok. So the solution I came up with for my Unit Test, is to get all the instances that implement IMotorController and assert that their count equals 1:
var motorControllerInstances = container.GetAllInstances<IMotorController>().Select(x => x); // cast enumerable to List using Linq
Assert.True(motorControllerInstances.Count == 1);
Not sure this is the most elegant way, but it seems to work.
Update 1:
This code does not catch the bug I had. I am still looking for a correct answer to my problem.
Update 2: I am getting closer. This will at least catch if you have accidentally registered a concrete type of the corresponding interface. However, it does not appear to check whether an instance of it was actually built.
var allInterfaceInstances = dicFixture.result.Model.GetAllPossible<IMotorController>();
Assert.True(allInterfaceInstance.Count() == 1);
In trying to adhere to the D in SOLID
Dependency inversion principle where
one should “Depend upon Abstractions. Do not depend upon concretions
for a project. In this case Asp.Net-MVC5, I wanted a way to make sure that all controllers (MVC and WebAPI2) were following this pattern where they were not dependent on concretions.
The original idea came from an article I had read where a unit test was created to scan all controllers to make sure that they had explicit authorization defined. I applied a similar thinking in checking that all controllers had constructors that depended on abstractions.
[TestClass]
public class ControllerDependencyTests : ControllerUnitTests {
[TestMethod]
public void All_Controllers_Should_Depend_Upon_Abstractions() {
var controllers = UnitTestHelper.GetAssemblySources() //note this is custom code to get the assemblies to reflect.
.SelectMany(assembly => assembly.GetTypes())
.Where(t => typeof(IController).IsAssignableFrom(t) || typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(t));
var constructors = controllers
.SelectMany(type => type.GetConstructors())
.Where(constructor => {
var parameters = constructor.GetParameters();
var result = constructor.IsPublic
&& parameters.Length > 0
&& parameters.Any(arg => arg.ParameterType.IsClass && !arg.ParameterType.IsAbstract);
return result;
});
// produce a test failure error mssage if any controllers are uncovered
if (constructors.Any()) {
var errorStrings = constructors
.Select(c => {
var parameters = string.Join(", ", c.GetParameters().Select(p => string.Format("{0} {1}", p.ParameterType.Name, p.Name)));
var ctor = string.Format("{0}({1})", c.DeclaringType.Name, parameters);
return ctor;
}).Distinct();
Assert.Fail(String.Format("\nType depends on concretion instead of its abstraction.\n{0} Found :\n{1}",
errorStrings.Count(),
String.Join(Environment.NewLine, errorStrings)));
}
}
}
So given the following example. (Note I adapted this to MVC)
public class MovementController : Controller {
public MovementController(MotorController motorController) {
//...
}
}
public interface IMotorController {
//...
}
public class MotorController : IMotorController {
//...
}
the unit test would fail with ...
Result Message: Assert.Fail failed.
Type depends on concretion instead of its abstraction.
1 Found :
MovementController(MotorController motorController)
This worked for me because I had a common type to look for with the IController and ApiController.
There is room for improvement on the test but is should be a good starting point for you.

Linq Where Condtion For Different Types

I have a list that is derived from ProfileBase. This list can contains an instance of Profile,,DynamicViewProfile because both are derived from ProfileBase
But If the item type is DynamicViewProfile, i must use NodeName, if Profile then I should use DocName
profileListsForSearch = profileLists.Where(stringToCheck =>
((Profile)stringToCheck).DocName.Contains(searchBar.Text)).ToList();
So this is for profile and it is OK, but if the list contains DynamicViewProfile objects then i have an exception, because docname is null and i need to get NodeName
I hope my questions is clear
There's nothing special about LINQ here - you basically write the same code as you would normally, using is or as:
string searchText = searchBar.Text;
profileListsForSearch = profileLists
.Where(profile =>
profile is Profile
? ((Profile)profile).DocName.Contains(searchText)
: ((DynamicViewProfile)profile).NodeName.Contains(searchText))
.ToList();
That's assuming those are the only two types involved. If your list contains some other type, you'd get an InvalidCastException.
However, this is pretty ugly - it feels like ProfileBase should expose some property or method which indicates the general name - and then that could be implemented to return DocName in Profile and NodeName in DynamicViewProfile. Then you'd just need:
string searchText = searchBar.Text;
profileListsForSearch = profileLists
.Where(profile => profile.Name.Contains(searchText))
.ToList();
It's also future-proof in terms of adding new subclasses of ProfileBase - and generally a cleaner use of polymorphism. Every time you need to cast - particularly conditionally casting to one thing or the other - consider whether a common method/property is feasible to make it cleaner.
You can use the is to check the object and the use the ternary operator to apply the condition on the object.
var result = profileLists.Where(stringToCheck =>stringToCheck is Profile ?
((Profile)stringToCheck).DocName.Contains(searchBar.Text)
: ((DynamicViewProfile)stringToCheck).NodeName.Contains(searchBar.Text)).ToList();
profileListsForSearch = profileLists.Where(p =>
{
if(p is Profile) return ((Profile)p).DocName.Contains(searchBar.Text));
if(p is DynamicViewProfile) return ((DynamicViewProfile)p).NodeName.Contains(searchBar.Text));
return false;
}).ToList();
You can check the types. But that really only means your class hierarchy is broken. If you derive, you should never be forced to explicitely check for a type.
Instead, you could have a property in your base class called FilterText which is implemented by the base class as return DocName; and by the derived class as return NodeName;. Then your code would look like this:
profileListsForSearch = profileLists.Where(p => p.FilterText.Contains(searchBar.Text)).ToList();

C# Reflection: GetMethods(..) failing to retrieve anything

I am currently trying to get a very specific set of methods but am failing to do so.
I need to get all methods that match a certain signature from all classes that implement a certain interface.
What I've got so far is:
IEnumerable<System.Type> classes = Assembly.GetAssembly(typeof(IActionMethod)).GetTypes().Where(x => x.GetInterface("IActionMethod") != null);
MethodInfo[] methods;
List<MethodInfo> relevant;
ParameterInfo[] parameters;
foreach(System.Type cls in classes)
{
methods = cls.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
relevant.Clear();
for(int i = 0; i < methods.Length; i++)
{
parameters = methods[i].GetParameters();
if(parameters.Length == 1 && parameters[0].GetType() == typeof(GameObject) && methods[i].ReturnType == typeof(void))
relevant.Add(methods[i]);
}
}
This code already fails at GetMethods(..)which is not returning any methods.
What I do not understand is, that I am able to receive all public methods of any of the relevant classes if they do not implement the interface.
The interface itself does not contain anything, I am only using it to "mark" the relevant classes, as I could not come up with any other solution to do so.
Can anyone tell me why the interface is rendering GetMethodsuseless or point me to the error in my code above?
I suspect this is the problem:
foreach(System.Type cls in classes)
{
methods = cls.GetType().GetMethods(...)
cls is already a Type, so calling GetType() on it will return System.Type (or a subclass). I suspect you just want:
foreach(System.Type cls in classes)
{
methods = cls.GetMethods(...)
It's also unclear why you're clearing the relevant list on each iteration. It means the only entries at the end will be the ones from the last class you look at - are you sure that's what you want?
As an aside, Microsoft recommends not using 'marker interfaces' and instead suggests using attributes. You can then use Memberinfo.IsDefined() instead of checking for the interface.
To find all classes that implements specific interface, you should use rather IsAssignableFrom because your code will omit classed that implement your interface indirectly:
Type interfaceType = typeof(IActionMethod);
Assembly assembly = Assembly.GetAssembly(interfaceType );
IEnumerable<System.Type> classes = assembly.GetTypes().Where(x => interfaceType.IsAssignableFrom(x));
Then, you probably want to call:
methods = cls.GetMethods(...)
because cls is your desired type, you are currently searching in its Type.

Moq Setup: ability to pass a value or It.IsAny<T>() depending on condition

[The question is similar to this: What is the difference between passing It.IsAny<int>() and the value of It.IsAny<int>() to a method setup - needing additional clarification]
Short version
(More definitions below)
I am in a situation where I need to setup mocks in a factory. Depending on the value, I want to choose between using it or It.IsAny<TTypeOfValue>().
This is what I (naively) wanted to do:
moq.Setup(() => mockWebService.WebServiceMethod(
webServiceMethodObject.Some ?? It.IsAny<string>(), // that fails
...,
out webServiceMethodObject.That,
...)).Returns(webServiceMethodObject.ReturnEnum);
I have such large parameterlists (old legacy webservice methods) and so much different combination of values that I don't want to write it by hand, nor using It.IsAny<T>() everywhere, as I want to control the return value depending on parameters.
A possible alternative should be the version, where I could match concrete values with concrete return types, and when no concrete values can be matched, it falls back to the broadest version (with all parameters substituted with It.IsAny<T>(). (Short example: in a login test I'd like to test different return values of different input parameters of a login method. In all other tests I'd just like to return LoginSuccess).
How can I achieve this? Only with some Expression/Reflection magic?
Longer explanation
This is how our typical legacy webservice looks like:
ReturnValueEnum WebServiceMethod(string some, int thing, ..., out int that, out byte[] those, ...) { ... }
We had so many webservice method calls needed and they are so bloated with parameters, that we had to come up with encapsulating them in objects.
Example:
public class WebServiceMethodObject
{
public string Some { get; set; }
public int Thing { get; set; }
...
public ReturnValue ReturnEnum { get; set; }
}
The strategy should be this: we are creating a default version of this object. In the tests we fill up values that needed to be matched. We would like to pass the object to a to-be-written method, which sets up the mock accordingly:
if a property is set: use that value
else: use It.IsAny<T>() (see the Setup above!).
I would've thought that if
webServiceMethodObject.Some ?? It.IsAny<string>()
is what you want but doesn't work, the simple substitution would be
It.Is<string>(v =>
webServiceMethodObject.Some == null ||
webServiceMethodObject.Some == v)
If the logic for the parameters is so complex you can safely use It.IsAny<T> for all parameters and define a custom delegate to process the method call:
moq
.Setup(() => WebServiceMethod(It.IsAny<string>(), It.IsAny<int>(), ...))
.Returns((some, thing, ...) => {
if (some == webServiceMethodObject.Some || webServiceMethodObject.Some == null) ...
{
return webServiceMethodObject.ReturnEnum;
}
});
If you look into the list of Returns overloads you see that there is a wealth of options, the "hardcoded" .Returns(some value) being only one of those.
As far as I know the the whole thing passed to setup is an expression tree. Moq then inspects the expression subtrees for the parameters. If they are It based expressions they are used for advanced logic. If not they are evaluated and the value is matched with the input. This is probably the/one reason why your naïve version is not working.

How can I use reflection or alternative to create function calls programatically?

I'm a bit of a novice with Reflection. I'm hoping that it's possible to do what I'd like it to. I've been working through ProjectEuler to learn the language, and I have a base class called Problem. Every individual PE problem is a separate class, i.e. Problem16. To run my calculations, I use the following code:
using System;
using Euler.Problems;
using Euler.Library;
namespace Euler
{
static class Program
{
[STAThread]
static void Main()
{
Problem prob = new Problem27();
}
}
}
I have completed 50 problems now, and I want to create a loop to run them all. My base class Problem has a method that appends to a text file the problem number, the answer, and the execution time that's called in each class's default constructor. I could manually change the function call for all 50, but as I continue to complete problems, this will end up being a lot of work.
I'd much rather do it programatically. I was hoping for this pseudocode become a reality:
for (int i = 1; i <= 50; i++)
{
string statement = "Problem prob = new Problem" + i + "();";
// Execute statement
}
with reflections, you can do much nicer things.
for example, declare an interface
interface IEulerProblem
{
void SolveProblem();
}
write your classes which are derived from IEulerProblem.
then you can run all within (technically) one nice line of code:
Assembly.GetEntryAssembly()
.GetTypes()
.Where(t => typeof(IEulerProblem).IsAssignableFrom(t))
.Where(t => !t.IsInterface && !t.IsAbstract)
.Select(t => Activator.CreateInstance(t) as IEulerProblem)
.OrderBy(t => t.GetType().Name).ToList()
.ForEach(p => p.SolveProblem());
First take a look at Get all inherited classes of an abstract class which applies to non-abstract classes as well.
Then you can simply call the method on the base class for each.
foreach (problem p in problems)
{
p.MyMethod()
}
Yes, this is possible, you'll want to read up on MethodInfo.Invoke: http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.invoke.aspx
var problems = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => !t.IsAbstract && typeof(Problem).IsAssignableFrom(t));
foreach(var p in problems)
{
var euler = Activator.CreateInstance(p) as Problem;
euler.Solve(); // ??
}
As one of the possible solutions, I would like to propose to create list of constructor delegates without the use of reflection.
You will still have to populate the list 50 times, but only once. You will have typesafety though and can specify different constructors for each of the derived classes. Something like this:
List<Func<Test>> tests = new List<Func<Test>>();
tests.Add(() => new Test1());
tests.Add(() => new Test2());
foreach (var constructor in tests)
{
Test test = constructor();
}

Categories

Resources