Is it possible to have a method in a base class to modify a derived class' properties? I was thinking something like this:
public class baseclass
{
public void changeProperties(string propertyName, string newValue)
{
try
{
this.propertyName = newValue;
}
catch
{
throw new NullReferenceException("Property doesn't exist!");
}
}
}
You can solve your problem via reflection, because this reference's type will be equal actual type, i.e. type of derived class:
Solution:
public class baseclass
{
public void changeProperties(string propertyName, object newValue)
{
var prop = GetType().GetProperty(propertyName);
if (prop == null)
throw new NullReferenceException("Property doesn't exist!");
else
prop.SetValue(this, newValue);
}
}
Implementation:
public class Test : baseclass
{
public int Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
var test = new Test();
test.changeProperties("Age", 2);
}
}
Related
I am trying to serialize custom EntityData class into Eyeshot proprietary file format. There is a great article about this (https://devdept.zendesk.com/hc/en-us/articles/360003318873-Eyeshot-Proprietary-File-Format),
it works fine if I serialize base class, however I can't serialize a class that is derived from my base class. Here is a sample, I tried to keep it as small as possible(please read comments along the way):
public class BaseClass
{
public int Id { get; set; }
public virtual BaseClassSurrogate ConvertToSurrogate() { return new BaseClassSurrogate(this); }
}
public class BaseClassSurrogate : Surrogate<BaseClass>
{
public BaseClassSurrogate(BaseClass myBaseClass) : base(myBaseClass) { }
public int Id { get; set; }
protected override BaseClass ConvertToObject()
{
var baseClass = new BaseClass();
CopyDataToObject(baseClass);
return baseClass;
}
protected override void CopyDataFromObject(BaseClass obj) { Id = obj.Id; }
protected override void CopyDataToObject(BaseClass obj) { obj.Id = this.Id; }
public static implicit operator BaseClass(BaseClassSurrogate surrogate) { return surrogate?.ConvertToObject(); }
public static implicit operator BaseClassSurrogate(BaseClass source) { return source?.ConvertToSurrogate(); }
}
And my derived class with its surrogate implementation:
public class DerivedClass : BaseClass
{
public int Number { get; set; }
public override BaseClassSurrogate ConvertToSurrogate() { return new DerivedClassSurrogate(this); }
}
public class DerivedClassSurrogate : BaseClassSurrogate
{
public DerivedClassSurrogate(DerivedClass baseClass) : base(baseClass) { }
public int Number { get; set; }
protected override BaseClass ConvertToObject()
{
var derivedClass= new DerivedClass();
CopyDataToObject(derivedClass);
return derivedClass;
}
protected override void CopyDataFromObject(BaseClass obj)
{
if (obj is DerivedClass derivedClass)
Number = derivedClass.Number;
base.CopyDataFromObject(obj);
}
protected override void CopyDataToObject(BaseClass obj)
{
if (obj is DerivedClass derivedClass)
derivedClass.Number = Number;
base.CopyDataToObject(obj);
}
//I don't understand do I need to call these in derived class as well?
//public static implicit operator BaseClass(BaseClassSurrogate surrogate) { return surrogate?.ConvertToObject(); }
//public static implicit operator BaseClassSurrogate(BaseClass source) { return source?.ConvertToSurrogate(); }
}
And here is FillModel method from FileSerializer class:
protected override void FillModel()
{
base.FillModel();
Model.Add(typeof(BaseClass), false)
.SetSurrogate(typeof(BaseClassSurrogate));
MetaType mt1 = Model[typeof(BaseClassSurrogate)]
.Add(1, "Id");
mt1.SetCallbacks(null, null, "BeforeDeserialize", null);
mt1.UseConstructor = false;
Model.Add(typeof(DerivedClass), false)
.SetSurrogate(typeof(DerivedClassSurrogate));
MetaType mt2 = Model[typeof(DerivedClassSurrogate)]
.Add(1, "Number");
mt2.SetCallbacks(null, null, "BeforeDeserialize", null);
mt2.UseConstructor = false;
}
This code gives me error:"No suitable conversion operator found for surrogate DerivedClass/DerivedClassSurrogate". Any help would be highly appreciated.
In FillModel() method you forgot to specify the hierarchy for your custom classes, try in this way:
protected override void FillModel()
{
base.FillModel();
Model.Add(typeof(BaseClass), false)
.AddSubType(1001, typeof(DerivedClass))
.SetSurrogate(typeof(BaseClassSurrogate));
Model[typeof(BaseClassSurrogate)]
.AddSubType(1001, typeof(DerivedClassSurrogate))
.Add(1, "Id")
.SetCallbacks(null, null, "BeforeDeserialize", null)
.UseConstructor = false;
Model[typeof(DerivedClassSurrogate)]
.Add(1, "Number")
.UseConstructor = false;
}
I'm trying to set an attribute on a method when I create the object but not sure how to go about it (or if it's possible).
This is what I've tried so far:
public abstract class AbstractClass
{
public abstract string DynamicAttributeValue { get; }
public AbstractClass()
{
// Set the Attribute on THIS instance
TypeDescriptor.AddAttributes(typeof(AbstractClass).GetMethod("MyMethod"),
new Attribute[] {
new ConditionalAttribute(DynamicAttributeValue)
});
}
public void MyMethod()
{
}
}
class MyConcreteClass : AbstractClass
{
public override string DynamicAttributeValue => "MyRunTimeValue";
static void Main(string[] args)
{
MyConcreteClass myClass = new MyConcreteClass();
string callingMethodName = "MyMethod";
MethodInfo methodInfo = myClass.GetType().GetMethod(callingMethodName);
var attributes = methodInfo.GetCustomAttributes();
}
}
I have a ParentClass. Two classes are inherit from it, FirstChildClass and SecondChildClass. A class MultipleValueTypes contains a Dictionary and a method that adds values to it. My intention is to be able to pass values of different classes, which inherit from the same abstract class to the value parameter of the Dictionary. Therefore, I initialize the dictionary with the value List<ParentClass> so that I would be able to add objects made with the child classes to the Dictionary. I can do this, but I cannot access them, therefore in the abstract class I create a way to tell them apart, a virtual method that both the children classes override to return their own class type.
I test the values they return against the enum itself and based on whether the condition is fulfilled, the object would be casted as what it is instead of a List<ParentClass>. Is this the wrong approach? Is this impossible?
I think it should work, because in my thinking the FirstObject and SecondObject are still objects of their respective classes, so casting should work and I should be able to access the overridden method.
What doesn't work: I cannot access the method that returns what type of class it is, because it only gets methods from the List<ParentClass>.
What I've tried so far: searching for a way to access the method, but I did not find any.
What I still need help with: everything mentioned above.
public abstract class ParentClass
{
public string Name { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
}
public class FirstChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public FirstChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the FirstChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public SecondChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the SecondChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public Dictionary<string, List<ParentClass>> ADictionary = new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if (!ADictionary.ContainsKey(Name))
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
class Program
{
static void Main(string[] args)
{
FirstChildClass FirstObject = new FirstChildClass("FirstObject");
SecondChildClass SecondObject = new SecondChildClass("SecondObject");
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if(TestDictionary.ADictionary["FirstObject"].TypeOfClass() == ParentClass.ChildClasses.FirstChildClass) ///List<ParentClass>' does not contain a definition for 'TypeOfClass' and no accessible extension method 'TypeOfClass' accepting a first argument of type 'List<ParentClass>' could be found (are you missing a using directive or an assembly reference?)
{
TestDictionary.ADictionary["FirstObject"] = (FirstChildClass)TestDictionary.ADictionary["FirstObject"]; ///Cannot convert type 'System.Collections.Generic.List<Dictionary.ParentClass>' to 'Dictionary.FirstChildClass
}
}
}
You forgot to use indexer of the list value of the key of the dictionary here:
==> TestDictionary.ADictionary["FirstObject"][0]
Here is your code now refactored too:
class Program
{
static void Main(string[] args)
{
var FirstObject = new FirstChildClass("FirstObject");
var SecondObject = new SecondChildClass("SecondObject");
FirstObject.ReturnMessage();
SecondObject.ReturnMessage();
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if ( TestDictionary.ADictionary["FirstObject"][0].TypeOfClass()
== ParentClass.ChildClasses.FirstChildClass )
{
TestDictionary.ADictionary["FirstObject"][0]
= (FirstChildClass)TestDictionary.ADictionary["FirstObject"][0];
}
Console.ReadKey();
}
}
public abstract class ParentClass
{
public string Name { get; set; }
public string RandomValue { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public virtual void ReturnMessage()
{
Console.WriteLine($"This is the {this.GetType().Name} instance");
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
}
public class FirstChildClass : ParentClass
{
public FirstChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
public SecondChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public readonly Dictionary<string, List<ParentClass>> ADictionary
= new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if ( !ADictionary.ContainsKey(Name) )
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
If the intention is to cast the whole list from List<ParentClass> to List<FirstChildClass> and List<SecondChildClass>, then Linq is your friend, just use the Cast function:
List<FirstChildClass> firstChildClasses = TestDictionary.ADictionary["FirstObject"]
.Cast<FirstChildClass>().ToList();
List<SecondChildClass> secondChildClasses = TestDictionary.ADictionary["SecondObject"]
.Cast<SecondChildClass>().ToList();
I need to be able to access a protected property/method on an object with the common base class to the calling scope. The compiler doesn't seem to like this at all.
class Base
{
protected int Data { get; set; }
}
class SubClasss1 : Base
{
}
class SubClasss2 :Base
{
public SubClasss1 MyFunction() {
SubClasss1 x = new SubClasss1();
x.Data = this.Data; // NOT HAPPY
return x;
}
}
I've figured this may work, but it doesn't
((Base)copy).Data = ...
This does work but is a bit ugly
class Base
{
protected int Data { get; set; }
protected int GetData(Base obj) { return obj.Data; }
protected void SetData(Base obj, int value) { obj.Data = value; }
}
class SubClasss1 : Base
{
}
class SubClasss2 : Base
{
public SubClasss1 MyFunction()
{
SubClasss1 x = new SubClasss1();
this.SetData(x, this.Data);
return x;
}
}
I was trying to avoid using protected internal as I don't want to clutter the public interface within the project.
This is because protected member can be accessed with in the derived class not outside of it. What you can do is add it to constructor like:
class SubClasss1 : Base
{
public SubClasss1(int data)
{
Data = data; // can be accessed within the class but not from outside
}
}
and then you would need to provide it:
class SubClasss2 : Base
{
public SubClasss1 MyFunction()
{
SubClasss1 copy = new SubClasss1(this.Data);
return copy;
}
}
One way can be create public set method in SubClasss2 and then you should be able to read the value of it and set it into SubClass1 in your Myfucntion.
class Base
{
protected int Data { get; set; }
protected int GetData(Base obj) { return obj.Data; }
protected void SetData(Base obj, int value) { obj.Data = value; }
}
class SubClasss1 : Base
{
public void SetData(Base obj, int value) { this.Data = value; }
}
class SubClasss2 : Base
{
public void SetData(Base obj, int value) { this.Data = value; }
public SubClasss1 MyFunction()
{
SubClasss1 x = new SubClasss1();
x.SetData(x, this.Data);
return x;
}
}
class Program
{
static void Main(string[] args)
{
SubClasss2 subClass2Obj= new SubClasss2();
subClass2Obj.SetData(subClass2Obj, 30);
var subClass1Obj = subClass2Obj.MyFunction();
}
}
I've been searching for a while now and tested several methods, but i didn't find the answer i was looking for. I'll try to explain.
I have an object with several fields/properties. These properties have custom attributes.
What i want is to get the custom attribute from a specific propertie without all the knowlege of the object.
The are the base classes
// FieldAttr has a public Text propery
public class TestObject
{
// Declare fields
[FieldAttr("prop_testfld1")]
public FLDtype1 testfld1 = new FLDtype1();
[FieldAttr("prop_testfld2")]
public FLDtype2 testfld2 = new FLDtype2();
[FieldAttr("prop_testfld3")]
public FLDtype1 testfld3;
}
public class FLDtype1
{
public string Value { get; set; }
}
public class FLDtype2
{
public Guid Value { get; set; }
}
public sealed class FieldAttr: System.Attribute
{
private string _txt;
public EntityFieldType(string txt)
{
this._text = txt;
}
public string Text { get { return this._text; } }
}
And i want to be able to do this in my application:
static void Main(string[] args)
{
TestObject test = new TestObject();
// (Option 1: preferred)
Console.WriteLine(test.testfld1.getFieldAttr().Text);
// (Option 2)
Console.WriteLine(test.getFieldAttr(test.testfld1).Text);
}
Is this possible? I've seen methods to get custom attribute values from all properties/fields of an object, but not for a specific field.
I've got a working method to get custom attribute from an enum, but wasn't able to recreate it for object fields/properties. This is because i couldn't get the name of the field i was trying to explore, because (for example) test.testfld1.ToString() give's me "ns.FLDtype1".
Looking forward for the answer :)
(and excuse my english)
Yes it is possible:
public static class Extensions
{
public static FieldAttr GetFieldAttr(
this TestObject source,
Expression<Func<TestObject,object>> field)
{
var member = field.Body as MemberExpression;
if (member == null) return null; // or throw exception
var fieldName = member.Member.Name;
var test = typeof (TestObject);
var fieldType = test.GetField(fieldName);
if (fieldType != null)
{
var attribute = fieldType.GetCustomAttribute<FieldAttr>();
return attribute;
}
return null;
}
}
Usage:
TestObject test = new TestObject();
var attr = test.GetFieldAttr(x => x.testfld3);
if(attr != null) Console.WriteLine(attr.Text);
Here is the fiddle
After another day of trial and error I decided to make use of Selman22 answer with a little modification. This is code I created:
public class TestObject : iTestObject
{
// Declare fields
[FieldAttr("prop_testfld1")]
public FLDtype1 testfld1 = new FLDtype1();
[FieldAttr("prop_testfld2")]
public FLDtype2 testfld2 = new FLDtype2();
[FieldAttr("prop_testfld3")]
public FLDtype1 testfld3;
}
public class FLDtype1 : iField
{
public string Value { get; set; }
}
public class FLDtype2 : iField
{
public Guid Value { get; set; }
}
public sealed class FieldAttr: System.Attribute
{
private string _txt;
public FieldAttr(string txt)
{
this._txt = txt;
}
public string Text { get { return this._txt; } }
}
public interface iField { }
public interface iTestObject { }
public static class Extensions
{
public static FieldAttr GetFieldAttr<T>(this T source, Expression<Func<iField>> field) where T : iTestObject
{
// Get member body. If no body present, return null
MemberExpression member = (MemberExpression)field.Body;
if (member == null) { return null; }
// Get field info. If no field info present, return null
FieldInfo fieldType = typeof(T).GetField(member.Member.Name);
if (fieldType == null) { return null; }
// Return custom attribute
return fieldType.GetCustomAttribute<FieldAttr>();
}
}
Usage:
public class Program
{
public static void Main()
{
TestObject test = new TestObject();
Console.WriteLine(test.GetFieldAttr(() => test.testfld1).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld2).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld3).Text);
}
}
Uses:
using System;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;
I have implemented interfaces to protect the GetFieldAttr method
#Sulman22: Thnx for the response!