I have following design problem programming application in C#.
I have classes A and B that both derives from C. I cannot change theirs definition because they are defined in external assembly and are not defined as partial too.
What I am trying to achieve is to differ functionality basing on weather provided C object is of type A or B. Of course I dont want to use if statements comparing runtime types of provided object. Is it possible with extensions methods? I dont think so.
Any solution? :)
It should be possible with extension methods by using generics.
Multiple approaches are possible, but this one is simplest. Although you do get that if
public static void Foo<T>(this T objectC)
where T: C
{
if(typeof(T)==typeof(B){ //or for runtime check: if(objectC is B)
//specific
}
}
you could then call Foo on any instance of A or B.
You mention you don´t want if statements, but I'm not sure to which extend you're trying to avoid that? The only way to completely avoid it, is to have 2 extension methods, one for A and one for B, (which in turn can call a common method for C), but I think you're trying to avoid multiple extension methods?
edit If you absolutely want to prevent if's, you'll have to use multiple extension methods as shown in Frederik's post. You could add an extension for the baseclass as well, that only gets called if the type is not known during compilation. But that would still need an if ;)
public static void Foo(this A a)
{
}
public static void Foo(this B b)
{
}
public static void Foo(this C c)
{
if(c is A)
Foo((A)c);
else if(c is B)
Foo((B)c);
else
throw new NotSupportedException(c.GetType().FullName);
}
If the type is always known at compile time, you can simply use the 2 extension methods for A en B.
You could try this:
public static class CExtensions {
public static void DoIt( this B foo ) {}
public static void DoIt( this A foo ) {}
}
But, I don't think that this will work:
C x = new A();
x.DoIt();
I don't think it will compile, but, I can't test it right now.
Purely from a feasibility point of view, it is possible using reflection and extension methods. Whether it makes sense in the context of your application, is something you should judge. Here goes the solution....
class C
{
}
class A : C
{
}
class B : C
{
}
static class Extender
{
public static void M(this B b)
{
Console.WriteLine(" Extension method on B");
}
public static void M(this A a)
{
Console.WriteLine(" Extension method on A");
}
}
static void Main(string[] args)
{
C c = new A();// The actual instance here will be created using some factory.
object instance = Activator.CreateInstance(c.GetType());
Type typeToFind = c.GetType();
Type typeToQuery = typeof(Extender);
var query = from method in typeToQuery.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == typeToFind
select method;
// You would be invoking the method based on its name. This is just a quick demo.
foreach (MethodInfo m in query)
{
m.Invoke(instance, new object[] { instance });
}
}
To me this feels like a flaw in design.
If you can't have a common class to two sub classes which override and changes functionality without knowing the run time type you clearly have some issues with the overall design.
Should that functionality that differ depending on run time types really reside in those classes at all?
You could do it this way. Create a class with the different methods you need. In the same class define a delegate with the signature of this methods and keep a Dictionary where the keys are the types, and the values the delegates. Finally you can create an extension method for your class C that look into the dictionary using the type of the object that's executing the method itself and executes the right method. Something like this:
public static class CExtender
{
private static void DoItA(C anA)
{
MessageBox.Show("A");
}
private static void DoItB(C aB)
{
MessageBox.Show("B");
}
private static void DoItC(C aC)
{
MessageBox.Show("C");
}
delegate void DoItDel(C aC);
private static Dictionary<Type, DoItDel> _doItDels;
private static Dictionary<Type, DoItDel> DoItDels
{
get
{
if (_doItDels == null)
{
_doItDels = new Dictionary<Type, DoItDel>();
_doItDels[typeof(A)] = new DoItDel(DoItA);
_doItDels[typeof(B)] = new DoItDel(DoItB);
}
return _doItDels;
}
}
// the only public part is the extension method
public static void DoIt(this C aC)
{
DoItDel aDel;
if (DoItDels.TryGetValue(aC.GetType(), out aDel))
aDel(aC);
else
DoItC(aC);
}
}
You can use Decorater pattern in this case.
i.e. you can have 2 new classes of your own let say A1, B1 both deriving from C. (provided C is not a sealed class. If that's the case solution would be a bit different). Also A1 and B1 needs to wrap A and B corespondingly. You could inject instances of A and B through the constructors of A1 and B1.
You can also have a common interface which A1 and B1 both implmement. Interface needs to have the method which you need A1 and B1 to implement in their own ways. (A1 and B1 can delegate the calls to A or B as needed)
This way, in your client code, you can refer to A1 and B1 instances by their interface type and perform the common operation defined in the interface without knowing what their actual concrete implementations are.
Let me know if you need a code sample if I wasn't clear.
OK I found the answer.
The dynamic keyword is the clue here.
We can write:
void Handle(C c)
{
dynamic cc = c;
HandleSpecific(cc);
}
void HandleSpecific(A a)
{
//Specific behavior A
}
void HandleSpecific(B b)
{
//Specific behavior B
}
Drawbacks are of course - Risk of exception beacause of runtime binding introduced here and slight performance hit.
Related
I didn't find the answer to my question, but it seems simple. The main big issue is that I bought some library and some functionality hardcoded inside the dll and I can't to recompile that dll without source code. So here is the school level issue:
We have 2 classes A and B
class A {
public void Method1() {
this.Method2 ();
}
private void Method2() {
WriteLine ("A");
}
}
class B : A {
private void Method2() {
WriteLine ("B");
}
}
If we call 'new B().Method1()', then we have the string line "A".
We can't do anything with the class A, but we can change the class B. We should get the string "B".
I've tried to use 'new' modifier, but, as you know, it does not help. The answer "Just override Method1 also" is not the option, cause the real code is much bigger.
Any suggestions?
It sounds to me like you are trying to override Method2 in order to get Method1 to print "B". However, since Method2 is private and non-virtual in class A, this is impossible as defined by C#'s language.
If we can compromise to find a different approach to achieve your desired results, here are some suggestions.
Class composition as a modified boiler plate:
class B
{
private A;
public void Method1() {
this.Method2 ();
}
private void Method2() {
WriteLine("B");
}
public void KeptMethod() {
a.KeptMethod();
}
}
Reflection to call/modify private members:
typeof(A).GetField("privateValue", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(a, "injected string");
typeof(A).GetMethod("privateMethod", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(a, new object[0]);
I know that both of these have there draw backs and limitations, but since I don't know your actual goal, I'm finding it difficult to be more specific.
I have given the following example of code:
public static class A
{
private static B _b;
public static B GetB
{
get
{
if(_b == null)
{
_b = B.load();
}
return _b;
}
}
public static void Save()
{
if(_b == null)
{
_b = B.load();
}
_b.Save()
}
}
public class B
{
public string Value{ get; set;}
public void Save()
{
//value is being save to somewhere
}
public static B load()
{
B b = new B();
// .....
//b.Value is loaded from somewhere
// ......
return b;
}
}
The next following is that I need to solve:
A.GetB.Value = "value"; // OK
B.Load().Value = "value"; // I need to prevent this
Above two lines of code does exactly same stuff but...
B.Load().Value should be inaccessible from any other place except for in Class A
Please let me know if anyone have an idea...
Thanks,
Fivee
Basically what you are trying to do is to not nest class B inside class A, and still have class A have an exclusive access to Bs fields. If A and B are independent classes, this is against encapsulation.
You are looking for friend classes. These types of classes are allowed in C++. C# does not support friend classes and the closest thing we have to friend classes are friend assemblies. See this post.
So if you really want that feature, you need to make them nested as others suggested.
Also, in case you wind up doing the nested class solution. Here is an absolutely beautiful way of handling access of a nested class's private member only to its container class. It's a little hacky but still...
I think that another solution might be to make B a public class (as it is already), and make B.Load an internal method. However, this would only work if you are calling A.GetB from another assembly (and plan on only this being the case).
I have the following situation:
In a 3rd party library (can not be modified):
class A { public virtual void M() {} }
class B : A { public override void M() {} }
In my own code:
class C : B { public override void M() {} }
From C's implementation of method M I want to call A's (but not B's!!). Can I?
Any tricks accepted, reflection included. I tried reflection already, but using the MethodInfo that I get from typeof(A) still generates a virtual call (calling C's implementation with subsequent stack overflow).
Deriving C from A is out of the question due to the complexity of reimplementing B.
you can generate dynamic method to make proxy that use Call (not CallVirt) instruction
var x = new C();
var m = typeof (A).GetMethod("M");
var dm = new DynamicMethod("proxy", typeof (void), new [] {typeof(C)}, typeof (C));
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
var action = (Action<C>)dm.CreateDelegate(typeof (Action<C>));
action(x);
Quite old question but I had a similar problem recently.
desco's answer gave the crucial hint.
But the generated proxy delegate should be encapsulated in class C, can be static and initialized via static constructor so time consuming reflection will be required only once.
// -- in foreign assembly
class A { public virtual void M() { Console.WriteLine("A.M"); }}
class B : A {public override void M() { Console.WriteLine("B.M"); }}
//
// -- in own assembly
class C : B
{
private static Action<C> call_A_M;
public override void M() {
call_A_M(this);
Console.WriteLine("C.M");
}
static C()
{
var m = typeof(A).GetMethod("M");
var dm = new DynamicMethod("", typeof(void), new[] { typeof(C) }, typeof(C));
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
call_A_M = (Action<C>)dm.CreateDelegate(typeof(Action<C>));
}
}
But as Dan Bryant already mentioned: never ever use such dirty tricks in production code.
In my previous answer I missed the fact that A and B are in an external library and cannot be modified. In that case, I would suggest a different approach. Basically, if the design flaw is in B, you can’t use B. Subclass from A instead.
The unfortunate consequence of this, of course, is that you may need to reimplement some or all of the functionality in B. You may be able to copy the code from Reflector if necessary. I realise that this sounds undesirable, but I still think it is preferable to using unmodifiable code that has a known issue that causes you problems.
I’m afraid this is not possible directly the way you describe — the purpose of virtual methods is for the overriding to be transparent. So the only way to do this at all is via a workaround.
Let me try to whip one up, but please be aware that this is a hacky suggestion. If you really need this construct in your code, it may be an indication that your code has a fundamental design flaw somewhere else, so restructuring something might be more desirable than filling it with yet another design flaw. But anyway, here goes...
class A {
public virtual void M() { m_protected(); }
protected void m_protected() { /* code goes here */ }
}
class B {
public override void M() { /* code here, possibly invoking base.M() */ }
}
class C {
public override void M() { m_protected(); }
}
You cannot do that. You should probably design your class hierarchy differently, because it looks strange that C inherits from B, while behaving like A.
Anyway, it could make sense in your case. Then you should make another method in A which you will not override:
class A {
protected virtual void basicM() {}
public virtual void M() { basicM(); }
}
class C {
public override void M() { basicM(); }
}
BTW, if you name the method as I did in the example, then you should probably rethink the whole thing. If this hierarchy is justified, than basicM probably performs something that deserves to be a separate method with a different name, perhaps even a public method.
interfaces provide a useful abstraction capability. One can have a class Foo implement some interfaces, say A, B, and C. Some client code may get a reference of type A, others one of type B, etc. each actually the same Foo object but the interface exposing only a narrow subset of the functionality. Of course, evil client code can try to cast the A reference to Foo, then access the other functionality.How to prevent this?
This is called a "malicious cast" and you can prevent it by having a wrapper that implements only the narrow interface you want to expose (by delegating to a private reference to the object that you would have otherwise directly passed to the evil client).
However, if the client is not only evil, but powerful as well, he might be able to use reflection to get to the hidden reference anyway.
Normal inheritance will always allow it, you can do nothing with it. If you want to expose some class as interface but hide other methods use Adapter pattern (google it)
You can't. One workaround is to implement three proxy classes, one to implement each interface, that forward all calls to a single Foo instance.
The person who performs a malicious cast does so at their own risk. In almost all cases, you can safely assume that the user will not use an object in a manner outside the specified interface contract.
The only time you really need to use a proxy object is if you are exposing security-sensitive object to untrusted code. Otherwise, spend your time making clear documentation about how objects can be used and work under the assumption that it will be followed.
Hide the underlying object.
Let's say you have:
public interface A {
}
public class B implements A {
}
So, interface A implements just a subset of B's functionality. Effectively it hides parts of B. Your question is how to stop the user from downcasting A to a B.
B objectOfTypeB = (B)objectOfTypeA; // you don't want this
So, don't give the user access to class B. If the user can't import it, he can't instantiate it or downcast to it. So, he's force to use the interface and nothing more.
Change the above code to:
/* Publicly accessable interface */
public interface A {
}
/* Class hidden inside the package. */
public class B implements A {
}
Then, you can just have a function return an A, secure in the knowledge that the user can't use B.
/* Function that returns an A. */
public A foo() {
/* ... */
return objectOfTypeB;
}
You can use a Facade class.
This class should wrap a delegate of class Foo and then only expose interface methods of, say A and just forward them to the delegate.
On the other hand, you can prevent casting to Foo by declaring it package private and have a public factory method that returns just the interface A ( which in reality is Foo ). That way casting from other packages will not be possible ( still, somebody may play tricks with reflection ).
There is no really practical, non-invasive way to protect against this.
However, if your situation really requires this protection, use this utility class to create dynamic proxy (delegate) classes (adapted from Dynamic Proxy Classes - <50 lines of production code!!).
This will cause ClassCastExceptions at runtime if someone uses tries a malicious cast. You could even conditionalize the code to turn it off at production time (have newInstance() just return obj - the object to as the "proxy").
DynamicProxy.java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DynamicProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj, Class<?>... interfaces) {
if (interfaces == null || interfaces.length == 0) {
throw new IllegalArgumentException("No interfaces");
}
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
interfaces,
new DynamicProxy(obj));
}
private DynamicProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
result = m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
}
return result;
}
// ** DEMO CODE BELOW HERE **
interface A {
void methodA();
}
interface B {
void methodB();
}
static class Foo implements A, B {
public void methodA() { System.out.println("A"); }
public void methodB() { System.out.println("B"); }
}
public static void main(String[] args) {
Foo foo = new Foo(); // implements both interfaces
// calls foo's methods, but only A methods
A a = (A) DynamicProxy.newInstance(foo, A.class);
// calls foo's methods, but only B methods
B b = (B) DynamicProxy.newInstance(foo, B.class);
// calls foo's methods, but only B methods
A ab = (A) DynamicProxy.newInstance(foo, A.class, B.class);
a.methodA();
b.methodB();
ab.methodA();
((B) ab).methodB();
// ClassCastException: $Proxy0 cannot be cast to DynamicProxy$Foo
((Foo) a).methodA();
// ClassCastException: $Proxy1 cannot be cast to DynamicProxy$Foo
((Foo) b).methodB();
// ClassCastException: $Proxy0 cannot be cast to DynamicProxy$B
((B) a).methodB();
// ClassCastException: $DynamicProxy1 cannot be cast to DynamicProxy$A
((A) b).methodA();
}
}
In C# is it possible to create a function that can only be called from within another function?
e.g., can you do something like this?
private void a()
{
b();
c();
...do something else
private void b()
{
..do something but can only be called from a()
}
private void c()
{
..do something but can only be called from a()
}
}
The reason I want to do this is that function b() and c() split some implentation details of a() and they are just cleaner and easier to read in their own scope. However, these functions are of no use to the class as a() does some handling after they are called which must take place.
Use an anonymous nested function maybe?
I wouldn't worry about taking explicit steps to ensure b() and c() are only called by a().
It makes sense to worry about the public methods you expose on a class, since you're providing an interface to the outside world, potentially to people who don't have access to the source code of your class (or at the very least don't want to worry about the implementation details of your class).
Inside your class, though, you should feel free to have whatever private methods you want for whatever reasons you want. Code re-use is one reason to create a new private method, but creating multiple smaller, single-use methods to break up a larger one is also a perfectly valid (and common) reason.
Beyond that, for future maintainers of your code a simple comment like:
//this method should only be called by a()
private void b()
{
...
}
is going to be far more understandable than most of the other solutions presented here.
Using a delegate you can do:
public voidMyFunction()
{
Func<string> myFunction=(s)=>Console.WriteLine(s);
foreach(string str in myStringList)
{
myFunction(str);
}
}
The short answer is no; however, you can create an anonymous delegate or lambda expression as your internal b() method.
You could use the StackFrame class to check at runtime who's the caller of the function:
public class MyClass
{
public static void A()
{
B();
}
public static void B()
{
var stackTrace = new StackTrace();
if (stackTrace.FrameCount < 1 || stackTrace.GetFrame(1).GetMethod() != typeof(MyClass).GetMethod("A"))
throw new InvalidOperationException("Not called from A()");
}
}
But that is
1) Only at runtime
2) Slow
3) A really dirty hack
Well you could use reflection and just get the calling method name and throw an exception if it were anything other than A.
http://www.csharp-examples.net/reflection-calling-method-name/
But if b and c are private they can only be called from within that class anyway, and if you're the only one that is writing the class, then i fail to see the problem. So it seems to me its not a coding problem but rather one of policy.
I'd just document the intent in the method headers/comments.
Similar Question Here - Note the comments on the answer
Not exactly but you could implement both within their own class. Mark b() as private.
To gain the effect of only a() calling b(), either do as Andrew noted already, by putting a() and b() in a class and marking b() appropriately. If you're working inside of an assembly that you control totally, you could use internal instead of private if a() and b() will be in different classes, but in the same assembly. Then user code cannot call it (from outside of your assembly, that is, from their application program) and you can control via policy the writing of your assembly.
You can also create something like this:
internal abstract class SecretFunctionWrapper
{
private void MySecretFunction()
{
...
}
protected void FunctionWhichCalls()
{
...
MySecretFunction();
}
}
public MyRealClass : SecretFunctionWrapper
{
...
}
This will work only for one function. You can also try nested private class like this:
public class A
{
private static class Wrapped
{
private static void A()
{
secred code
}
public static void B()
{
A();
}
}
public void UsingA()
{
Wrapped.B();
}
}
i dont know but maybe Code by Contracts may help but this is not supported natively
Maybe easier to use #region in this case
You could use the internal keyword and put both those functions inside the same class, while leaving other other functions in a different class:
http://msdn.microsoft.com/en-us/library/7c5ka91b.aspx