I have a property Data in a class BaseLVItem
namespace Spo.Plugins
{
public class BaseLVItem : System.Windows.Forms.ListViewItem
{
public virtual IBaseObject Data
{
get{ return m_data; }
}
private IBaseObject m_data = null;
we used it properly like shown below in a class ResourcePolicySystemsLVI
public class ResourcePolicySystemsLVI : BaseLVItem
{
public new IResourcePolicy Data
{
get
{
return (IResourcePolicy)base.Data;
}
}}
but when i used in the following class i am getting error 'System.ComponentModel.StringConverter' does not contain a definition for 'Data'
using Spo.Plugins;
public class ResourcePolicyConverter : StringConverter
{
public new IResourcePolicy Data
{
get
{
return (IResourcePolicy)base.Data;
}
}
i am not able to implement BaseLVItem class here,Can any body guide me here
Dixon i am implementing like this
public class ResourcePolicyConverter : StringConverter
{
BaseLVItem lvItem = new BaseLVItem();
IResourcePolicy data = (IResourcePolicy)lvItem.Data;
--------------------
else if ((value == null) && data.AgentVersion != null )
{
return m_nullPolicy;
}
It's because your class ResourcePolicyConverter is inheriting from StringConverter rather than BaseLVItem. A typo?
The reason you cannot use the Data property in your second example is that ResourcePolicyConverter doesn't inherit from BaseLVItem and thus, the Data property is not available in the base.
You can simply instantiate a new BaseLVItem and then access the Data property.
BaseLVItem lvItem = new BaseLVItem();
IResourcePolicy data = (IResourcePolicy)lvItem.Data;
Related
I am looking for a way to support multi level of inheritance for generic type constraint.
Common generic interface
public interface ICommon<T>
{
T OrignalData {get;set;}
string ChangeJson {get;set;}
T Merged {get;set;}
void Inject();
}
Common base class implements ICommon
public class Base <T>: ICommon<T>
{
public T OrignalData {get;private set;}
public string ChangeJson {get;set;}
public T Merged {get;private set;}
public void Inject(T orignal)
{
if (orignal == null)
return;
var settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
dynamic merged = orignal.Clone();
JsonConvert.PopulateObject(this.ChangeJson, merged, settings);
this.Merged = merged;
this.Orignal = orignal;
}
}
Department class inherits Base class
public class Deparment : Base<Deparment>
{
}
OrgnizationDepartment class inherits Deparment
public class OrgnizationDepartment : Deparment
{
}
class View expect ICommon must implement on passed calls
public class View<T> where T : ICommon<T>
{
//This class is totally dynamic to visualize any json data along with old and new value of requested json for any class like department or org..
}
Test
public class Test
{
public void TestConstraint()
{
//No error
var deptView = new View<Deparment>();
//Error as Base not directly implemented on OrgnizationDepartment
var orgView = new View<OrgnizationDepartment>();
}
}
how do I define my constraint that should support for multi level as well.
One way out of this would be "composition over inheritance".
Here is a naive example, that is still relatively close to your code:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
//No error
var deptView = new View<Deparment>();
//Formerly Error
var orgView = new View<OrgnizationDepartment>();
}
}
public interface ICommon<T> where T : ICloneable
{
// returns a tuple
(T,T,string) Inject(T original, string change);
}
public class Base <T>: ICommon<T> where T : ICloneable
{
// we can reuse this...
private readonly JsonSerializerSettings settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
public (T,T,string) Inject(T original, string change)
{
if (original is null)
return default;
// this forces T to implement ICloneable ... just saying...
dynamic merged = original.Clone();
JsonConvert.PopulateObject(change, merged, settings);
return (original, merged, change);
}
}
public class Deparment : ICloneable, ICommon<Deparment>
{
// could also be created in ctor. Maybe use Ctor injection.
private readonly Base<Deparment> common = new Base<Deparment>();
public object Clone(){return this;} // this is of course nonsense. Clone properly! I did this to avoid dotnetfiddle screaming at me.
public (Deparment, Deparment, string) Inject(Deparment original, string change){
return common.Inject(original, change);
}
}
public class OrgnizationDepartment : ICloneable, ICommon<OrgnizationDepartment>
{
private readonly Base<OrgnizationDepartment> common = new Base<OrgnizationDepartment>();
public object Clone() {return this;}
public (OrgnizationDepartment, OrgnizationDepartment, string) Inject(OrgnizationDepartment original, string change){
return common.Inject(original, change);
}
}
Here is my generic method from which i want to return the class object
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Above method calling the below static generic class which will handle object creation of a particular class
public static class PageObjectBase<T> where T : class, new()
{
private static T singleTonObject;
public static T PageObject
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if (singleTonObject == null)
{
singleTonObject = new T();
}
return singleTonObject;
}
}
How can i call the PageObject property from my test base class please advice.
Note : I have searched forum and find answers relevant to generic method to another generic method calling.The same is achieved by reflection.Can we use reflection in my case too? If so how can we do it.
You can add another constraint 'class' to NavigateandReturntheObject
public T NavigateandReturntheObject<T>() where T : class,new()
Complete Code.
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : class,new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Demo Code
public class TestClass
{
public string Name{get;set;}
public TestClass()
{
Name = "Dummy Name";
}
}
var testBase = new TestBase();
var sample = testBase.NavigateandReturntheObject<TestClass>();
Console.WriteLine(sample.Name);
Output
Dummy Name
I want to know if there is a way I can create generic getter and setter methods for the below code.
Currently the setter checks the actual type of the input object and adds it to the relevant list. It feels like a bad approach to me, but I'd like to know if there is a better way.
I can't use any other data structures like a dictionary because I am using a serialisation system that can only serialise simple collection types like Lists and arrays, hence all the individual lists.
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc
public class GlobalStyle : ASerializedObject
{
public List<ImageStyle> ImageStyles = new List<ImageStyle>();
public List<TextStyle> TextStyles = new List<TextStyle>();
public List<ButtonStyle> ButtonStyles = new List<ButtonStyle>();
//... etc
// Setter
public void SetStyle(BaseStyleType inStyle)
{
if (inStyle as ImageStyle != null)
ImageStyles.Add((ImageStyle)inStyle);
else if (inStyle as TextStyle != null)
TextStyles.Add((TextStyle)inStyle);
else if (inStyle as ButtonStyle != null)
ButtonStyles.Add((ButtonStyle)inStyle);
//... etc
}
// Getter
public T GetStyle<T>(int index)
{
//...?
}
}
Thanks
Just because you can't use things for serialization purposes shouldn't prevent you from actually using them.
The advantage to the following solution is you can infinitely create derives classes from BaseStyleType (or other super types) and you'd only have to create the properties to access the dictionary.
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
// NOT THREAD SAFE
public class GlobalStyle
{
//
private Dictionary<Type,List<BaseStyleType>> _lists =
new Dictionary<Type,List<BaseStyleType>>();
// Not sure why you'd use Fields here...
public IEnumerable<ImageStyle> ImageStyles
{
get
{
IEnumerable<ImageStyle> result = null;
List<BaseStyleType> list;
if (_lists.TryGetValue(typeof(ImageStyle), out list))
{
result = list.Cast<ImageStyle>();
}
return result;
}
}
//etc
//public List<ImageStyle> ImageStyles = new List<ImageStyle>();
//public List<TextStyle> TextStyles = new List<TextStyle>();
//public List<ButtonStyle> ButtonStyles = new List<ButtonStyle>();
// Setter
public void SetStyle<T>(T inStyle)
where T : BaseStyleType
{
List<BaseStyleType> list;
if (_lists.TryGetValue(typeof(T), out list))
{
list.Add(inStyle);
}
else
{
list = new List<BaseStyleType>();
list.Add(inStyle);
_lists.Add(typeof(T), list);
}
}
}
I see two ways at least:
1) You got a simple, flat herarchy. Make only lists of BaseStyleType. Let covariance and automatic upcasting take care of the details.
2) Modify your code somewhat like that:
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc
public class GlobalStyle <List1Type, List2Type, List3Type, ... > : ASerializedObject
{
public List<List1Type> ImageStyles = new List<List1Type>();
public List<List2Type> TextStyles = new List<List2Type>();
public List<List3Type> ButtonStyles = new List<List3Type>();
//... etc
// Setter
public void SetStyle(BaseStyleType inStyle)
{
if (inStyle as ImageStyle != null)
ImageStyles.Add((ImageStyle)inStyle);
else if (inStyle as TextStyle != null)
TextStyles.Add((TextStyle)inStyle);
else if (inStyle as ButtonStyle != null)
ButtonStyles.Add((ButtonStyle)inStyle);
//... etc
}
// Getter
public T GetStyle<T>(int index)
{
//...?
}
}
The problem with long type lists is that you end up having to use lines like
GlobalStyle <ImageStyle , TextStyle, ButtonStyle> every single time a the type is needed (field types, return types, paramters, etc.). Starting with two generic placeholders, it is usually a good idea to make a type alias.
using CustomGlobalStyle = GlobalStyle <ImageStyle, TextStyle, ButtonStyle>;
I have a Part base class
class Part {
public PartType Type { get; set; }
}
with many implementations.
class Wire : Part { }
I have a TreeView in my program. And when I click on an element of it, I want a list to be filled with all the Parts of the Type I clicked in the TreeView.
When I have multiple lists open I want only those be loading the parts that have the same PartType as I clicked in the TreeView.
class BasePartListViewModel<T> : ListViewModel where T : Part {
protected override void OnTreeSelectionChanged(PartType type)
if (type == PartType.Wire) {
//load the Wires from the DB and display them
}
else {
//ignore the changed type event
}
}
}
But since this is a base class for all Parts by using T I would like to replace
if (_type == PartTypeEnum.Wire)
with something like
if (_type == T.Type)
but that does of course not work. How else?
Since the part type is a static information for a class type by design (am I right?), you could use an attribute to store it:
[AttributeUsage(AttributeTargets.Class)]
public class PartTypeAttribute : Attribute
{
public readonly PartType PartType;
public PartTypeAttribute(PartType partType)
{
PartType = partType;
}
}
Then apply it to the descendant classes:
[PartType(PartType.Wire)]
class Wire : Part
{
}
Then in the static constructor of the BasePartListViewModel class you can obtian the corresponding value:
class BasePartListViewModel<T> : ListViewModel
where T : Part
{
private static PartType PartTypeOfT;
static BasePartListViewModel()
{
var attr = typeof(T).GetCustomAttributes(typeof(PartTypeAttribute), true)
.FirstOrDefault() as PartTypeAttribute;
if (attr != null)
PartTypeOfT = attr.PartType;
}
protected override void OnTreeSelectionChanged(PartType type)
{
if (type == PartTypeOfT) {
....
}
}
}
If you do this.GetType() it will return as BasePartListViewModel`1[Wire]
You should not be ideally referring this in the base class.
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;