I'm using Ninject to instantiate some objects with a constructor arg passed, e.g.:
class MyClass
{
public MyClass(string myArg)
{
this.myArg = myArg;
}
}
The number of instances I need of this class won't be known until runtime, but what I want to do is ensure that each variation of myArg results in a different singleton instance (so asking for the same value twice returns the same instance, but different args return different instances).
Does anyone know of a good, preferably built-in, way of doing this?
I found an article written for an older version of Ninject How To Ensure One Instance per Variation of Activation Parameters but was hoping there'd be a tidier solution for the newer version.
Edit
Here's what I went with, adapted from Akim's answer below:
private readonly ConcurrentBag<string> scopeParameters = new ConcurrentBag<string>();
internal object ParameterScope(IContext context, string parameterName)
{
var param = context.Parameters.First(p => p.Name.Equals(parameterName));
var paramValue = param.GetValue(context, context.Request.Target) as string;
paramValue = string.Intern(paramValue);
if (paramValue != null && !scopeParameters.Contains(paramValue))
{
scopeParameters.Add(paramValue);
}
return paramValue;
}
public override void Load()
{
Bind<MyClass>()
.ToSelf()
.InScope(c => ParameterScope(c, "myArg"));
Bind<IMyClassFactory>()
.ToFactory();
}
You could achieve require behaviour by providing custom scope using IBindingNamedWithOrOnSyntax<T> InScope(Func<IContext, object> scope) method for MyClass binding
Indicates that instances activated via the binding should be re-used
as long as the object returned by the provided callback remains alive
(that is, has not been garbage collected).
So, you need to return value of first constructor argument from Func<IContext, object> scopeand make sure that garbage-collector would not collect it.
Here is a snippet:
public class Module : NinjectModule
{
// stores string myArg to protect from CG
ConcurrentBag<string> ParamSet = new ConcurrentBag<string>();
public override void Load()
{
Bind<MyClass>()
.ToSelf()
// custom scope
.InScope((context) =>
{
// get first constructor argument
var param = context.Parameters.First().GetValue(context, context.Request.Target) as string;
// retrieves system reference to string
param = string.Intern(param);
// protect value from CG
if(param != null && ParamSet.Contains(param))
{
// protect from GC
ParamSet.Add(param);
}
// make Ninject to return same instance for this argument
return param;
});
}
}
ps: full sample code with unittests
Related
I'm trying to create something like a pool of exemplar's class and use its methods.
public class PoolOfObjects
{
public delegate Object InstanceCreation();
public Object[] objects;
bool?[] State;
InstanceCreation _creator;
Type _type;
public PoolOfObjects(Type type, int objects_count, InstanceCreation creator)
{
objects = new object[objects_count];
State = new bool?[objects_count];
for (int i = 0; i < objects_count; i++)
objects[i] = _creator;
}
//Must return an exemplar by state of object when called
public Object EjectObject (bool? state)
{
int i;
for (i = 0; i < State.Length; i++)
if (State[i] == state)
{ //create object if null
if (objects[i] == null)
objects[i] = _creator;
break;
}
return objects[i];
}
}
Here is an example of some class, what i have to create in pool
public class Test
{
public Test()
{
Console.WriteLine("constructor");
}
public void SomeMethod()
{
Console.WriteLine("SomeMethod");
}
}
and then I try to use it like this
PoolOfObjects pool = new PoolOfObjects(typeof(Test),27,delegate {
return new Test();
});
pool.EjectObject(null).SomeMethod();
But it's haven't seen a method, because return type — object. I have try to convert object[] to Type, but i get "object must implement iconvertible" exception.
Maybe there are some easy and simple ways to initialize object[] like this:
object = new (type)[object_count]
or something else?
Thanks for your answers!
Yes, you can. The syntax you've predicted is very similar.
An array can have a type of the objects it's containing:
T[] array = new T[size];
where T is the type (class, struct) you want the array to hold. Based off your code in your case it would be InstanceCreation.
It would be a nice time to tackle with C# Generics for you. Take a look at System.Collections.Generic.List<T>.
You can indeed "Cast" your object to a specific type.
object stringAsObject = "This is a string";
string stringAsString = (string)stringAsObject;
But in this case I would recommend using Generics. Creating generic methods can be a bit complex in some cases - luckily I do not believe this is one of them.
With generics you do not have to change everything to an "object" and the compiler can keep track of the types for you. This will allow it to show a number of errors you have in your code.
To give you a starting point to work from, I have tried changing your object pool class into a generic implementation here. I added comments for things I changed and things you still need to work on. Notice I did not run this, just checked no error is highlighted in Visual Studio, so there might still be a few things you need to change once you start debugging. :)
// Changed to Generics. This makes the class easier to use.
public class PoolOfObjects<T>
{
// Changed to private - you do not want this accessible from the outside
// Changed the type to T so you do not have to cast.
private T[] _objects;
// Changed to prefix with _.
// Not all coding guidelines do this, but whatever you do be consistent.
// Changed to states as there appears to be on per object.
private bool?[] _states;
// Using the standard Func<T> (function returning T)
// instead of introducing a new delegate type
private Func<T> _creator;
// Changed to camelCase and Func<T> instead of custom delegate
public PoolOfObjects(int objectsCount, Func<T> creator)
{
// Changed to remember the creator
_creator = creator;
// I left this an array, but consider changing to List<T>,
// then the list can grow as needed.
_objects = new T[objectsCount];
_states = new bool?[objectsCount];
// removed initialization of objects
// as it appears you do it when calling EjectObject
}
//Must return an exemplar by state of object when called
public T EjectObject(bool? state)
{
// TODO:
// You never assign any values to the _states array,
// so it will always have the value null.
// this means if your method is called with true or false,
// it will FAIL!
// I do not know what "states" is for so I can't suggest how to fix it.
// If it is to track if an object is already in use I recommend getting
// rid of it and change your _objects to be:
// private Queue<T> _objects
// Then this method will check if there are any items in the _objects queue,
// if there is dequeue one and return it. If not, create a new object
// and return it.
// You then need to create another method to put the items back in the queue
// after use.
int i;
for (i = 0; i < _states.Length; i++)
if (_states[i] == state)
{ //create object if null
if (_objects[i] == null)
// Changed to call your creator instead of assigning it.
_objects[i] = _creator();
break;
}
// TODO: Your program will crash with an unclear error here if no object
// has a state matching the requested state.
return _objects[i];
}
}
Can't seem to find any useful guide on how to reproduce the functionality currently provided by a TypeInterceptor in my codebase when upgrading from StructureMap 2 to version 3 (can't upgrade to v4 as we aren't using .NET 4.6 yet).
Essentially what the interceptor does is this:
public class TheInterceptor : TypeInterceptor
{
private Dictionary<string, string> typesToIntercept;
public TheInterceptor(IDictionary<string, string> typesToIntercept)
{
// Passed in on ctor, comes from XML configuration section.
this.typesToIntercept = typesToIntercept;
}
public object Process(object target, StructureMap.IContext ctx)
{
var typedTarget = target as BaseType;
var key = target.GetType().FullName;
if (typedTarget == null || !typesToIntercept.ContainsKey(key))
{
return target;
}
var propertyOverrideType = typesToIntercept[key];
typedTarget.BaseProperty = ctx.GetInstance<IBaseInterface>(propertyOverrideType);
return typedTarget;
}
}
So we're basically maintaining a dictionary where the key is the type we want to intercept and the value is a specific type that implements a known interface, that we want to set on a property of the intercepted object.
FWIW I didn't write the original code, I just can't figure out what the correct way of mirroring this behaviour in StructureMap 3 would be. I feel like it's something that could be done without an interceptor, but I believe it was implemented like this so that this behaviour could be used across multiple sites (it's in a shared library) without each site having to explicitly deal with the interception behaviour, so if possible I would like to retain this usage.
So I eventually figured this out by trial-and-error. What you need is an ActivatorInterceptor and use the Action delegate to perform the logic that previously would have been inside the Process method of the TypeInterceptor. So from my code snippet above, it becomes:
public class InterceptorPolicy : IInterceptorPolicy
{
private readonly IDictionary<string, string> typesToIntercept;
public InterceptorPolicy(IDictionary<string, string> types)
{
this.typesToIntercept = types;
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (instance.ReturnedType.IsSubclassOf(typeof(BaseType)))
{
yield return new ActivatorInterceptor<BaseType>((ctx, x) => this.Activate(ctx, x));
}
}
private void Activate(IContext ctx, BaseType instance)
{
var key = instance.GetType().FullName;
if (this.typesToIntercept.ContainsKey(key))
{
var propertyOverrideType = this.typesToIntercept[key];
instance.BaseProperty = ctx.GetInstance<IBaseInterface>(propertyOverrideType);
}
}
}
Given an object, I would like to create a mock that implements the interface of the object and mocks one method, but forwards the rest of the methods to the real object, not the base class.
For example:
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
mock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...)
// Here I would like to delegate the rest of the methods to the real sqlUtil object. How ?
So, in the example I want to mock just ISqlUtil.SpecialMethodToBeMocked and forward the rest of methods/properties to the existing instance sqlUtil.
Is it possible in Moq.NET ?
EDIT 1
It should work for generic methods as well.
You can't do this with Moq out of the box. However, I think you can achieve basically what you want if you go down to the next layer and use Castle DynamicProxy directly (which is what's underneath Moq).
So, given the following base code to simulate your issue (essentially, an interface, a concrete implementation and a factory because the concrete is hard to make/setup):
public interface ISqlUtil {
T SomeGenericMethod<T>(T args);
int SomeMethodToIntercept();
}
public class ConcreteSqlUtil : ISqlUtil {
public T SomeGenericMethod<T>(T args){
return args;
}
public int SomeMethodToIntercept() {
return 42;
}
}
public class SqlUtilFactory {
public static ISqlUtil CreateSqlUtil() {
var rVal = new ConcreteSqlUtil();
// Some Complex setup
return rVal;
}
}
You can then have the following test:
public void TestCanInterceptMethods() {
// Create a concrete instance, using the factory
var coreInstance = SqlUtilFactory.CreateSqlUtil();
// Test that the concrete instance works
Assert.AreEqual(42, coreInstance.SomeMethodToIntercept());
Assert.AreEqual(40, coreInstance.SomeGenericMethod(40));
// Create a proxy generator (you'll probably want to put this
// somewhere static so that it's caching works if you use it)
var generator = new Castle.DynamicProxy.ProxyGenerator();
// Use the proxy to generate a new class that implements ISqlUtil
// Note the concrete instance is passed into the construction
// As is an instance of MethodInterceptor (see below)
var proxy = generator.CreateInterfaceProxyWithTarget<ISqlUtil>(coreInstance,
new MethodInterceptor<int>("SomeMethodToIntercept", 33));
// Check that calling via the proxy still delegates to existing
// generic method
Assert.AreEqual(45, proxy.SomeGenericMethod(45));
// Check that calling via the proxy returns the result we've specified
// for our intercepted method
Assert.AreEqual(33, proxy.SomeMethodToIntercept());
}
The method interceptor looks like this:
public class MethodInterceptor<T> : Castle.DynamicProxy.IInterceptor {
private T _returns;
private string _methodName;
public MethodInterceptor(string methodName, T returns) {
_returns = returns;
_methodName = methodName;
}
public void Intercept(IInvocation invocation) {
if (invocation.Method.Name == _methodName) {
invocation.ReturnValue = _returns;
}
else {
invocation.Proceed();
}
}
}
Essentially, the interceptor checks if the method being called matches the one you're interested in and if so, returns the stored return value. Otherwise, it calls Proceed, which delegates the method call onto the concrete object supplied when the proxy was created.
The example code uses strings rather than lambdas to specify the method to intercept, obviously this could be changed (exercise for the reader). Also, this isn't using Moq, so you lose the Setup, Returns and Verify elements, which are replaced by the Interceptor, so this may be too far away from what you're after to be useful, however depending what your code really looks like it may be a viable alternative approach.
If you're unable to mock the class and delegate calls to the base by default, then you'll have to manually wire up the delegation to your separate instance.
var util = GetSqlUtil();
var mockUtil = new Mock<ISqlUtil>(MockBehavior.Strict);
mockUtil.Setup(x => x.SomeCall(...)).Returns<...>(args => util.SomeCall(args));
Having been successful with tricking Moq into creating a proxy for given class instance in my other SO answer here, I thought it would be easy to tweak the solution for your case of a given interface implementation.
No way
If you think of, it it makes sense: interface has no implementateion. And since Moq is aware mocked type is an interface - it does not even try to call the underlying proxy. That's it, end of story.
For those who don't give up easily
spoiler: still no luck
Looking at the library source code, I had a theory that it might be possible to force the correct execution path:
if (mock.TargetType.IsInterface) // !!! needs to be true here
{
// !!! we end up here and proceed to `DefaultValueProvider`
}
else
{
Debug.Assert(mock.TargetType.IsClass); // !!! needs to pass here
Debug.Assert(mock.ImplementsInterface(declaringType)); // !!! needs to pass here
// Case 2: Explicitly implemented interface method of a class proxy.
......
for that we could fulfill two conditions:
mock.TargetType should be a target class instance type
this.InheritedInterfaces should contain our interface
the second one is easy enough to build:
private void AddInheritedInterfaces(T targetInstance)
{
var moqAssembly = Assembly.Load(nameof(Moq));
var mockType = moqAssembly.GetType("Moq.Mock`1");
var concreteType = mockType.MakeGenericType(typeof(T));
var fi = concreteType.GetField("inheritedInterfaces", BindingFlags.NonPublic | BindingFlags.Static);
var t = targetInstance.GetType()
.GetInterfaces()
.ToArray();
fi.SetValue(null, t);
}
but as far as I'm aware, overriding an expression-bodied property marked internal (which Mock<>.TargetType is) is impossible without Reflection.Emit artillery, where it will likely become infeasible due to amonunt of overriding and subclassing required - you might be better off just forking Moq and patching the source code in this case (or submitting a PR maybe?).
What can be done
It should be possible to generate Setup LINQ expressions that automatically call through to your respective instance implementations:
//something along these lines, but this is basically sudocode
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
foreach(var methodInfo in typeof(ISqlUtil).GetMembers())
{ mock.Setup(Expression.Member(methodInfo)).Returns(Expression.Lambda(Expression.Call(methodInfo)).Compile()())
}
But given how much effort it is to account for everything properly, that again is probably not very feasible.
There is a workaround to do it, by using the method by #timur described in this answer.
While this method doesn't work directly on interfaces as described by his answer in the current thread, but it is indeed possible to do it via a generic factory method.
NOTE: The resulting Moq object will NOT be a true subclass rather it is a wrapped object and therefore only public virtual methods will be forwarded to the object (unlike a typical Moq which the base is automatically called for non public or non virtual methods/properties).
The factory mode would look like this:
static MyMock<T> CreateMock<T>(T target) where T : class, ISqlUtil
{
var superMock = new MyMock<T>(target); // now we can pass instances!
superMock.CallBase = true;
superMock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...);
return superMock;
}
And you use it like this:
var mockFunc = typeof(this).GetMethod("CreateMock").MakeGenericMethod(sqlUtil.GetType());
var superMock = mockFunc.Invoke(null, new object[] {sqlUtil}) as Mock;
While the implementation of MyMock will be based on the one described in this answer (but I am simplifying it a bit).
public class MyMock<T> : Mock<T>, IDisposable where T : class
{
public MyMock(T targetInstance)
{
var moqAssembly = typeof(Mock).Assembly;
var proxyFactoryType = moqAssembly.GetType("Moq.ProxyFactory");
var castleProxyFactoryInstance = proxyFactoryType.GetProperty("Instance").GetValue(null);
var castleProxyFactoryType = moqAssembly.GetType("Moq.CastleProxyFactory");
var generatorFieldInfo = castleProxyFactoryType.GetField("generator", BindingFlags.NonPublic | BindingFlags.Instance);
generatorFieldInfo.SetValue(castleProxyFactoryInstance, new MyProxyGenerator(targetInstance));
}
}
class MyProxyGenerator : ProxyGenerator
{
object _target;
public MyProxyGenerator(object target) {
_target = target;
}
// this method is 90% taken from the library source. I only had to tweak two lines (see below)
public override object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
{
if (_target is not null) return CreateClassProxyWithTarget(classToProxy, additionalInterfacesToProxy, _target, options, constructorArguments, interceptors);
return base.CreateClassProxy(classToProxy, additionalInterfacesToProxy, options, constructorArguments, interceptors);
}
I've been struggling with this problem for a couple days, and I still am not sure how to solve it.
I've created a container extension for the Unity Container to enable me to easily register decorator classes in the container. This is the implementation I currently have, which is almost identical to the one in this article:
public class DecoratorExtension : UnityContainerExtension
{
private int m_order;
private Dictionary<Type, IList<DecoratorRegistration>> m_typeStacks;
protected override void Initialize()
{
m_typeStacks = new Dictionary<Type, IList<DecoratorRegistration>>();
Context.Registering += AddRegistration;
Context.Strategies.Add(new DecoratorBuildStrategy(m_typeStacks), UnityBuildStage.PreCreation);
}
private void AddRegistration(object _sender, RegisterEventArgs _e)
{
if (_e.TypeFrom == null || !_e.TypeFrom.IsInterface)
return;
GetStack(_e.TypeFrom)
.Add(new DecoratorRegistration {Order = m_order++, Type = _e.TypeTo});
}
private IList<DecoratorRegistration> GetStack(Type _type)
{
if (!m_typeStacks.ContainsKey(_type))
m_typeStacks.Add(_type, new List<DecoratorRegistration>());
return m_typeStacks[_type];
}
}
What this does is use a list for each type, to store all type registrations for the same target type, so that I can reassemble it when Resolve is called, using this build strategy:
internal class DecoratorBuildStrategy : BuilderStrategy
{
private readonly Dictionary<Type, IList<DecoratorRegistration>> m_typeStacks;
internal DecoratorBuildStrategy(Dictionary<Type, IList<DecoratorRegistration>> _typeStacks)
{
m_typeStacks = _typeStacks;
}
public override void PreBuildUp(IBuilderContext _context)
{
var key = _context.OriginalBuildKey;
if (_context.GetOverriddenResolver(key.Type) != null)
return;
// Only interfaces can use decorators.
if (!key.Type.IsInterface)
return;
// Gets the list of types required to build the 'decorated' instance.
// The list is reversed so that the least dependent types are built first.
var decoratorTypes = GetDecoratorTypes(key.Type).Reverse().ToList();
if (!decoratorTypes.Any())
return;
object value = null;
foreach (var type in decoratorTypes)
{
Type typeToBuild = type;
if (typeToBuild.IsGenericTypeDefinition)
{
Type[] genericArgumentTypes = key.Type.GetGenericArguments();
typeToBuild = typeToBuild.MakeGenericType(genericArgumentTypes);
}
value = _context.NewBuildUp(new NamedTypeBuildKey(typeToBuild, key.Name));
// An Override is created so that in the next BuildUp the already
// built object gets used instead of doing the BuildUp again and
// entering an infinite loop
_context.AddResolverOverrides(new DependencyOverride(key.Type, value));
}
_context.Existing = value;
_context.BuildComplete = true;
}
private IEnumerable<Type> GetDecoratorTypes(Type _type)
{
var typeList = m_typeStacks.GetValueOrDefault(_type) ?? new List<DecoratorRegistration>(0);
if (!_type.IsGenericType)
return typeList.Select(_reg => _reg.Type);
// If the type is a generic type, we need to get all open generic registrations
// alongside the closed ones
var openGenericList = m_typeStacks
.GetValueOrDefault(_type.GetGenericTypeDefinition()) ??
new List<DecoratorRegistration>(0);
// The final result is an ordered concatenation of the closed and open registrations
// that should be used for the type
return typeList
.Concat(openGenericList)
.OrderBy(_registration => _registration.Order)
.Select(_reg => _reg.Type);
}
}
This is where the DecoratorRegistration model is used. It is just a pair of type/int that represents the order of the registration. I created this to be able to mix open and closed generic registrations correctly:
internal struct DecoratorRegistration
{
public int Order { get; set; }
public Type Type { get; set; }
}
This works wonders for the most part. The problem started when I had a class that implemented two interfaces, one which was decorated, and one that wasn't.
This is the current test case I'm trying to make work:
private interface IAny<T> {}
private interface IAnotherInterface {}
private class Base<T> : IAnotherInterface, IAny<T> {}
private class Decorator1<T> : IAny<T>
{
internal readonly IAny<T> Decorated;
public Decorator1(IAny<T> _decorated)
{
Decorated = _decorated;
}
}
[TestMethod]
public void DecoratorExtensionDoesNotInterfereWithNormalRegistrations()
{
// Arrange
var container = new UnityContainer()
.AddNewExtension<DecoratorExtension>()
.RegisterType<Base<string>>(new ContainerControlledLifetimeManager())
.RegisterType<IAny<string>, Decorator1<string>>()
.RegisterType<IAny<string>, Base<string>>()
.RegisterType<IAnotherInterface, Base<string>>();
// Act
var decorated = container.Resolve<IAny<string>>();
var normal = container.Resolve<IAnotherInterface>();
var anotherDecorated = container.Resolve<IAny<string>>();
var anotherNormal = container.Resolve<IAnotherInterface>();
// Assert
Assert.IsInstanceOfType(normal, typeof (IAnotherInterface));
Assert.IsInstanceOfType(decorated, typeof (Decorator1<string>));
Assert.AreSame(normal, anotherNormal);
Assert.AreSame(decorated, anotherDecorated);
}
This test should make my intent clear. I wanted singleton classes, but the first call to Resolve, for either IAnotherInterface or IAny<string> results in every subsequent call to return the same thing. Thus, I get an exception:
System.InvalidCastException: Unable to cast object of type 'Decorator1`1[System.String]' to type 'IAnotherInterface'.
on this line:
var normal = container.Resolve<IAnotherInterface>();
I'm not sure what to do here. I had to temporarily disable singletons in our project so that this could work as intended. What I wanted is that the Base<string> instance was a sintleton, but when I requested a IAny<string> it would create a NEW instance with the SAME base being decorated.
This is still using .Net 4.0, so I'm stuck with Unity 2.1 here (shouldn't matter in this case though).
It's been a while since I've solved this, so I figured that it would be good to replicate the answer I got from Randy Levy from the EntLib team here.
It basically boils down to the build key I was using to register the decorator instance. With my code, the instance was actually registered with the base class type, while I needed to register it with the actual decorator type.
This post has the suggested workaround for the issue, which worked very nicely on our end.
I'm not exactly sure if this is what you're looking for, but I think this does the trick in the specific case in your test:
container.RegisterType<IAny<string>, Base<string>>(
new ContainerControlledLifetimeManager(), "Inner");
container.RegisterType<IAny<string>, Decorator1<string>>(
new InjectionConstructor(
new ResolvedParameter(typeof(IAny<string>), "Inner")));
container.Register<IAnotherInterface>(new InjectionFactory(
c => c.Resolve<IAny<string>>("Inner")));
You don't need that extension for that.
I need to examine in "parent" object is there an acceptable at a definite moment to call some method in the "child". For example, parent object (component) includes child objects (or component parts in other words) and parent is disposing now, so all (or particlar) child activities must be prohibited (i.e. starting new service threads, enqueueing new client requests, ...).
public class Parent
{
public bool IsMethodCallAcceptable(reference_to_method) {...}
}
public class Child
{
public int SomeMethod(int intArg, string stringArg)
{
if(!_parent.IsMethodCallAcceptable(reference_to_SomeMethod_with_actual_args))
throw new ...
...
}
private void AnotherMethod(string param = null) {...}
{
if(!_parent.IsMethodCallAcceptable(reference_to_AnotherMethod_with_actual_args))
throw new ...
...
}
private Guid ThirdMethod()
{
if(!_parent.IsMethodCallAcceptable(reference_to_ThirdMethod))
throw new ...
...
}
}
Is there any way to do it?
Note: I am answering your question, not your title. Others have answered the title.
Some objects have an isDisposed property, if your parent implements that and that is the only time you don't want to call methods, then yes. Otherwise no. If you control the source for the parent, you could add a property that does what you want.
If you don't control the source and you want to check more than isDisposed or the parent doesn't implement isDisposed, you might be able to check publicly exposed properties, but generally you should assume that if a method is exposed to the public, that it is acceptable to call it at any time. If you're calling private methods via reflection, then you're taking chances.
Edit in response to comment:
Given your description, delegates won't give you any additional capability that you can't do easier by adding properties and methods to the parent (if you don't control the source, they won't help at all). The best method for dealing with your described scenario (CAR.ENGINE.START when out of gas, is for the Start method to either throw an exception or return a value indicationg the result of the attempt to start the engine).
Use delegates?
http://msdn.microsoft.com/en-us/library/ms173171%28v=vs.80%29.aspx
The easiest way is to pass an URI instead of a reference:
"NS.Child.ThirdMethod" for example.
Otherwise, a delegate is what is the closest to a function reference. You can pass that if you want.
However, this method is not compliant with OOP conception rules: Base class should know nothing about its children classes.
It's better to use some kind of locking mechanism to tell the children that they can't have access to the resources.
use func Func<T, TResult>
link
If these methods are native to the child class, the parent can't know anything about them for sure. Rice's Theorem will cause you all kinds of problems, if you could even see the code. Same problem (but to a lesser degree) if they're native to the parent class and are being overridden in the child, since you can't really guarantee that the child class will be doing everything (and only those things) that the parent class does; in fact, you can all but guarantee it will do something different. (If it didn't, why override?)
If they're native to the parent class and not overridable in the child, then just check whether the object is in a valid state for doing such a thing and throw an exception if it isn't.
As far as the actual validity check, for your example you can have a method like bool IsDisposing(); for other cases, you might keep track of the state in some other way. A private method like CanDoThisThing() might help, for example. Having a method that takes a generic operation name (not an operation; we already established the infeasibility of that) seems kinda broken to me.
Thank you all again, the result in the first approach is listed below
public class Component
{
public ComponentPart SomeComponentPart1 { get; private set; }
public ComponentPart SomeComponentPart2 { get; private set; }
public Component()
{
SomeComponentPart1 = new ComponentPart(this);
SomeComponentPart2 = new ComponentPart(this);
}
public bool IsMethodCallAcceptable(MethodCallExpression method, object[] parameters)
{
// collect needed information about caller
var caller = (method.Object as ConstantExpression).Value;
var methodName = method.Method.Name;
var paramsArray = new Dictionary<string, object>();
for (int i = 0; i < method.Arguments.Count; i++)
paramsArray.Add((method.Arguments[i] as MemberExpression).Member.Name, parameters[i]);
// make corresponding decisions
if (caller == SomeComponentPart2)
if (methodName == "SomeMethod")
if ((int) paramsArray["intArg"] == 0 || (string) paramsArray["stringArg"] == "")
return false;
return true;
}
}
public class ComponentPart
{
private Component Owner { get; set; }
public ComponentPart(Component owner)
{
Owner = owner;
}
public int SomeMethod(int intArg, string stringArg)
{
// check if the method call with provided parameters is acceptable
Expression<Func<int, string, int>> expr = (i, s) => SomeMethod(intArg, stringArg);
if (!Owner.IsMethodCallAcceptable(expr.Body as MethodCallExpression, new object[] { intArg, stringArg }))
throw new Exception();
// do some work
return stringArg.Length + intArg;
}
public void AnotherMethod(bool boolArg, Dictionary<Guid, DateTime> crazyArg, string stringArg, object objectArg)
{
// check if the method call with provided parameters is acceptable
Expression<Action<bool, Dictionary<Guid, DateTime>, string, object>> expr =
(b, times, arg3, arg4) => AnotherMethod(boolArg, crazyArg, stringArg, objectArg);
if (!Owner.IsMethodCallAcceptable(expr.Body as MethodCallExpression, new [] { boolArg, crazyArg, stringArg, objectArg }))
throw new Exception();
// do some work
var g = new Guid();
var d = DateTime.UtcNow;
}
}
This is variant how to check method calls, the same approach can be used in order to check properties values changes, while some ComponentPart' methods and properties can check some public Component.State property (via ComponentPart.Owner) instead of calling Component.IsMethodCallAcceptable or Component.IsPropertyChangeAcceptable.