I've a function QMain() whose return type is object.
public class QMain
{
public object objQ(string str)
{
if (str.ToUpper() == "A")
{
clsA objA = new clsA();
return objA;
}
else if (str.ToUpper() == "B")
{
clsB objB = new clsB();
return objB;
}
else
return "";
}
}
Following is clsA:
public class clsA
{
public string strMessage { get; private set; }
public static string staticField;
public bool cantAccessThisFn(string str)
{...}
}
Both of the above classes are in same project which is a class library. I've created another console application wherein I've included the above project's dll. Now, I'm doing:
QMain obj=new QMain();
object A=obj.objQ("A");
I can get strMessage, staticField but not cantAccessThisFn. If I directly make an object of clsA, I'm able to get cantAccessThisFn. Is there any way to get access to this function from obj (object of class QMain)?
I get the following error:
'object' does not contain a definition for 'cantAccessThisFn' and no extension method 'cantAccessThisFn' accepting a first argument of
type 'object' could be found (are you missing a using directive or an
assembly reference?)
The problem is your objQ method returns an object. You haven't defined any (extension) methods on object, so cantAccessThisFn definitely can't be accessed.
What you should do is this: create an interface with all methods you want to share between the two classes, and don't return object, but return IYourInterfaceName. Then you can access those methods and properties defined on the interface.
Something like this:
public class clsA : IYourInterface
{
...
}
public interface IYourInterface
{
string strMessage { get; }
bool cantAccessThisFn(string str);
}
Then your method should look like:
public IYourInterface objQ(string str)
{ ... }
And your assignment like this:
IYourInterface a = obj.objQ("A");
Now it is valid to call:
a.cantAccessThisFn("z");
This is to help you understand! and not the recommended solution.
Marked Patricks answer up, as that is the more correct way...
but to achieve what you had you could do something like.
Also I applied the standard naming camel cases for the Classes, Properties and local variables.
This also allows for ClsA and ClsB to have completely different Method/Property names. Again I am not suggesting this as the way to do it but to rather help understand what its happening.
public class Program
{
static void Main()
{
QMain obj = new QMain();
object a = obj.objQ("A");
//FYI the below commended out is not possible...
//ClsA.staticField is but that is not the instance you created.
//------------
//a.staticField //<--- not possible
//------------
var someA = a as ClsA; //<--- attempts to cast it as ClsA
var someB = a as ClsB; //<--- attempts to cast it as ClsB
if (someA != null) //check if the cast was successful
{
var var1 = someA.StrMessage;
}
else if (someB != null)
{
//...
}
}
}
public class QMain
{
public object objQ(string str)
{
if (str.ToUpper() == "A")
{
ClsA objA = new ClsA();
return objA;
}
else if (str.ToUpper() == "B")
{
ClsB objB = new ClsB();
return objB;
}
else
return "";
}
}
public class ClsA
{
public string StrMessage { get; private set; }
public static string StaticField;
public bool CantAccessThisFn(string str)
{
return true;
}
}
public class ClsB
{
public string StrMessageMyC { get; private set; }
public static string StaticFieldMyC;
public bool CantAccessThisFnMyC(string str)
{
return true;
}
}
Related
I'm currently having trouble and I have no clue how to fix it.
I have 2 classes:
class A
{
public string MyParam { get; set; }
}
class B : A
{
public new string MyParam { get { return base.MyParam != null ? base.MyParam.Substring(1) : null; } }
}
When I try to access the B.MyParam it works when I have a the correct type, but in most of my methods I have a generic type
with :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class A
{
public string MyParam { get; set; }
}
public class B : A
{
public new string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
public static void MyMethod<T>(T variable) where T : A
{
Console.WriteLine(variable.MyParam);//this print hello
Console.WriteLine((variable as B).MyParam);//this print ello (exactly what i want)
Console.WriteLine(typeof(T)); // this print ConsoleApplication1.Program+A
Console.WriteLine(variable.GetType()); // this print ConsoleApplication1.Program+B
// so i need something like that
Console.WriteLine((variable as variable.GetType()).MyParam); // this line is invalid
}
static void Main(string[] args)
{
A a = new B();
a.MyParam = "Hello";
Console.WriteLine(a.GetType());
MyMethod(a);
Console.ReadKey();
}
}
}
Is there a way to do it?
Thank you in advance.
EDIT: it seems that what i want is :
dynamic variable2 = Convert.ChangeType(variable, variable.GetType());
Console.WriteLine(variable2.MyParam);
Your code doesn´t make any sense. If A inherits from B you´ll need A to override the base-implementation for your property. So I´ll assume you should rethink your inheritance-chain.
You can use override for this. Thus when your variable-parameter is of your base-class (I renamed that to A) you´re calling the base-method, if it´s a derived instance (here B) you´re calling the override:
class A
{
public virtual string MyParam { get; }
}
class B : A // note here that B derives from A, not the other way round
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; },
set { ... }
}
}
EDIT: While new intrduces a new member which (accidentally) has the same name (and signature) as the base-member it effectivly hides the base-member. Thus you effectivly have two members. Your only way to indicate which member should be used is by casting your instance to the desired class from which you need the implementation. However this somehow breaks the purpose of generics as the generic member has to know the exact types that are possible for the type-parameter.
Anyway this seems like broken design to me, as you´re actually creating a new member which has another meaning. So you should also give it a new name.
Based on your generic method, I think all you need is an interface.
public interface IMyParam
{
string MyParam { get; set; }
}
Your classes.
class A : IMyParam
{
public virtual string MyParam { get; set; }
}
class B : A
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
And your method, won't need to be generic.
public void MyMethod(IMyParam variable)
{
// Your logic here, for example.
Console.WriteLine(variable.MyParam);
}
Calling your method.
A a = new A();
a.MyParam = "Hello";
B b = new B();
b.MyParam = "Hello";
A ab = new B();
ab.MyParam = "Hello";
MyMethod(a); // Prints Hello
MyMethod(b); // Prints ello
MyMethod(ab); // Prints ello
There is tons of info about skipping Properties based on conditionals, but I would like to skip the entire object based on conditions within the object's class. I would like a solution that is contained within the object's class if at all possible. Keep in mind this is a collection of myObj that I am serializing.
public class myObj
{
bool conditional;
ShouldSerialize()
{
return conditional;
}
}
Or
public class myObj
{
[JsonCondition]
public bool conditional{get;}
}
Or even
[JsonCondition(typeof(MyConditionChecker))]
public class myObj
{
public bool conditional{get;}
}
class MyConditionChecker: JsonCondition
{
public override bool CanConvert(object sourceObj)
{
return (sourceObj as myObj).conditional;
}
}
What I got from your comments you would be best served creating your own wrapper around Json that applies the filtering.
public interface IConditionalSerializer
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional<T>(IEnumerable<T> input)
where T : IConiditionalSerializer
{
return JsonConvert.SerializeObject(input.Where(e => e.ShouldBeSerialized()));
}
}
public class Demo : IConditionalSerializer
{
public bool ShouldBeSerialized() => false;
}
You might also replace the interface with a reflection approach, but keep in mind the performance loss.
public interface IConiditionChecker
{
bool ShouldBeSerialized(object instance);
}
public class ConditionAttribute : Attribute
{
public Type ConditionChecker { get; set; }
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let att = entry.GetType().GetCustomAttribute<ConditionAttribute>()
let hasChecker = att != null && att.ConditionChecker != null
let checker = hasChecker ? (IConiditionChecker)Activator.CreateInstance(att.ConditionChecker) : null
where checker.ShouldBeSerialized(entry)
select entry);
return JsonConvert.SerializeObject(matches);
}
}
[Condition(ConditionChecker = typeof(SomeChecker))]
public class Demo
{
}
Edit: Based on your comment you could do this. Only must decide wether to use opt-in or opt-out in the where-statement. It must ether be casted != null && casted.ShouldBeSerialized or what it currently says.
public interface IShouldBeSerialized
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let casted = entry as IShouldBeSerialized
where casted == null || casted.ShouldBeSerialized()
select entry);
return JsonConvert.SerializeObject(matches);
}
}
public class Demo : IShouldBeSerialized
{
public bool ShouldBeSerialized()
{
return false;
}
}
If you're able to use the JSON.NET serializer, in terms of not serializing specific items within a collection, you could make the main collection non serializable, then add another filtered collection that does serialize.
public class Manager
{
[JsonIgnore]
public Employee[] Employees { get; set; }
[JsonProperty("Employees")]
public Employee[] SerializableEmployees
{
get { return Employees.Where(e => e.Name != "Bob").ToArray(); }
set { Employees = value; }
}
}
Alternatively, you could mark your class with the [JsonConverter] attribute and use a custom converter to check your condition. A similar approach that ignores a class entirely is detailed here.
I'm trying to make a design for some sort of IExecutable interface. I will not get into details, but the point is that I have several Actions that need to be executed from a base class. They may take different parameters (no big deal), and they may/may not return a value.
So far, this is my design:
public abstract class ActionBase
{
// ... snip ...
}
public abstract class ActionWithResultBase<T>: ActionBase
{
public abstract T Execute();
}
public abstract class ActionWithoutResultBase: ActionBase
{
public abstract void Execute();
}
So far, each of my concrete actions need to be a child from either ActionWithResultBase or ActionWithoutResult base, but I really don't like that. If I could move the definition of Execute to ActionBase, considering that the concrete class may or may not return a value, I will have achieved my goal.
Someone told me this could be done with using Func and Action, for which I totally agree, but I can't find a way to have that into one single class so that the caller would know if the action is going to return a value or not.
Brief: I want to do something like:
// Action1.Execute() returns something.
var a = new Action1();
var result = a.Execute();
// Action2.Execute() returns nothing.
var b = new Action2();
b.Execute();
If you want a lightweight solution, then the easiest option would be to write two concrete classes. One will contain a property of type Action and the other a property of type Func<T>:
public class ActionWithResult<T> : ActionBase {
public Func<T> Action { get; set; }
}
public class ActionWithoutResult : ActionBase {
public Action Action { get; set; }
}
Then you can construct the two types like this:
var a1 = new ActionWithResult<int> {
CanExecute = true,
Action = () => {
Console.WriteLine("hello!");
return 10;
}
}
If you don't want to make Action property read/write, then you could pass the action delegate as an argument to the constructor and make the property readonly.
The fact that C# needs two different delegates to represent functions and actions is quite annoying. One workaround that people use is to define a type Unit that represents "no return value" and use it instead of void. Then your type would be just Func<T> and you could use Func<Unit> instead of Action. The Unit type could look like this:
public class Unit {
public static Unit Value { get { return null; } }
}
To create a Func<Unit> value, you'll write:
Func<Unit> f = () => { /* ... */ return Unit.Value; }
The following interfaces should do the trick -- it's essentially copying the Nullable pattern
public interface IActionBase
{
bool HasResult { get; }
void Execute() { }
object Result { get; }
}
public interface IActionBase<T> : IActionBase
{
new T Result { get; }
}
public sealed class ActionWithReturnValue<T> : IActionBase<T>
{
public ActionWithReturnValue(Func<T> action) { _action = action; }
private Func<T> _action;
public bool HasResult { get; private set; }
object IActionBase.Result { get { return this.Result; } }
public T Result { get; private set; }
public void Execute()
{
HasResult = false;
Result = default(T);
try
{
Result = _action();
HasResult = true;
}
catch
{
HasResult = false;
Result = default(T);
}
}
}
public sealed class ActionWithoutReturnValue : IActionBase
{
public bool HasResult { get { return false; } }
object IActionBase.Result { get { return null; } }
public void Execute() { //... }
}
You know that you can ignore the return value of a method right? You don't have to use it.
what about something simple:
public class ActionExecuter
{
private MulticastDelegate del;
public ActionExecuter(MulticastDelegate del)
{
this.del = del;
}
public object Execute(params object[] p)
{
return del.DynamicInvoke(p);
}
}
Can somone explain why I get this error on this code?
Error 1 The type
'ConsoleApplication1.TestClass'
already contains a definition for
'IsThisOK'
class TestClass
{
public bool IsThisOK { get; set; }
public static bool IsThisOK(string str)
{
return true;
}
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = IsThisOK("Hello");
}
}
You're trying to define a property and a method with the same name. While you can have multiple methods that override each other (with different argument lists), you cannot have a property and a method that share the same name
You've declared IsThisOK twice, at line 3 and line 5 (property and static function).
Try to imagine how could the compiler could figure out to which you are referring later on?
Because you cannot provide same name to a function and a Property.
You cannot overload function with property.
You can use it in this way:
class TestClass
{
public bool IsThisOK { get; set; }
public static bool isThisOK(string str)
{
return true;
}
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = isThisOK("Hello");
}
}
As other pointed out, you cannot have a method and a property with the same name.
However, you can more or less work around this by using an extension method if you like:
static class TestClassExtension
{
public static bool IsThisOK(this TestClass, string str)
{
return true;
}
}
class TestClass
{
public bool IsThisOK { get; set; }
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = this.IsThisOK("Hello");
}
}
I need to have a wrapper class that exposes some properties of my entity class called ProfileEntity.
I tried doing it by deriving from this entity and then creating properties that return specific entity properties, but it says I cannot cast from ProfileEntity to ProfileEntityWrapper.
When I try to put the return values of a method that returns a 'ProfileEntity' into the wrapper I get the above error.
How do I create such a wrapper class that is castable?
Example
class ProfileEntityWrapper : ProfileEntity
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class Someclass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity; // example of method returning this object
}
}
public class SomeOtherlClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
ProfileEntityWrapper ew = (ProfileEntityWrapper)sc.SomeMethod(); // Cannot do this cast!!!
}
}
You cannot cast an object of ProfileEntity to ProfileEntityWrapper.
var entity = new ProfileEntity(); // this object is only of type ProfileEntity
var wrapper = new ProfileEntityWrapper(); // this object can be used as both ProfileEntityWrapper and ProfileEntity
You probably want to return a ProfileEntityWrapper in SomeMethod():
public class Someclass
{
public ProfileEntity SomeMethod()
{
return new ProfileEntityWrapper(); // it's legal to return a ProfileEntity
}
}
No, that is not possible.
To accomplish this problem you can maybe try this one:
public class ProfileEntity
{
public string ProfileEntityName { get; set; }
}
public class ProfileEntityWrapper
{
public ProfileEntityWrapper(ProfileEntity entity)
{
Entity = entity;
}
public ProfileEntity Entity { get; private set; }
public string Name
{
get
{
return Entity.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
// example of method returning this object
ProfileEntity temp = new ProfileEntity();
return temp;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
//Create a new Wrapper for an existing Entity
ProfileEntityWrapper ew = new ProfileEntityWrapper(sc.SomeMethod());
}
}
If you are allowed to edit the ProfileEntity class, or if the ProfileEntity class is a generated partial class, you could add an interface instead of using a wrapper. You wouldn't need to do any casting with an interface either. Example:
public interface IProfile
{
string Name { get; }
}
public partial class ProfileEntity : IProfile
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
IProfile ew = sc.SomeMethod();
}
}
The IProfile instance will only provide access to the Name property.
This's no correct code from polymorphism aspect.
If we will take the famous polymorphism example when there're base Shape class and Circle, Polygon and Rectangle classes that extend the Shape class, your code will try to cast some shape into circle and as you understand this's invalid casting operation.
So to make this code work you must be sure that SomeClass.SomeMethod() will return instance of ProfileEntityWrapper or perform type check before the casting, like this:
ProfileEntity temp = sc.SomeMethod();
if(temp is ProfileEntityWrapper)
ProfileEntityWrapper ew = (ProfileEntityWrapper) temp;