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.
Related
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 have an problem with this three classes.
In first class i'm extending for listview class for common method
In second class we put one method it's invoke by the 1st class
This is fine for above two classes but in my third class need to pass that T, M values.
But i don't understand how to do this?
anybody help this issue?
Thank you
1st Class
public class MyListView : ListView
{
public UserControl uc { get; set; }
internal MyLEvent<Type,Type> MyLEvnt { get; set; }
public MyListView()
{
PreviewKeyDown += new KeyEventHandler(MyListView_PreviewKeyDown);
}
private void MyListView_PreviewKeyDown(object sender,KeyEventArgs e)
{
ListView view = sender as ListView;
var item = view.SelectedItem;
if (item != null)
{
string str = item.GetType().Name;
if (e.Key == Key.Delete)
{
MyLEvnt.Method(item, "Delete");
}
else if (e.Key == Key.Enter)
{
MyLEvnt.Method(item, "Modify");
uc.GetType().GetProperty("Update").SetValue(uc, 1, null);
MethodInfo mi = uc.GetType().GetMethod("IClear");
mi.Invoke(uc, null);
}
}
}
}
2nd Class
public class MyLEvent<T,M> where T : class where M : class
{
private M manager;
private T type;
public MyLEvent()
{
}
public object Method(object _view, string flog)
{
object retVal = null;
type = Activator.CreateInstance<T>();
manager = Activator.CreateInstance<M>();
if (flog == "Modify")
{
MethodInfo method = typeof(M).GetMethod("getData");
type = (T)method.Invoke(manager, new[] { _view });
}
else if (flog == "Set")
{
MethodInfo method = typeof(M).GetMethod("setDefault");
retVal = method.Invoke(manager, new[] { _view });
}
else
{
if (MyMessage.askDelete() == true)
{
PropertyClass.Properties(_view, type, 'U');
MethodInfo method = typeof(M).GetMethod("Delete");
retVal = method.Invoke(manager, new[] { type });
}
}
return retVal;
}
}
3rd Class
public partial class SubASettings : UserControl
{
public SubASettings()
{
InitializeComponent();
MAILV.uc = this;
MAILV.MyLEvnt = new MyLEvent<typeof(InvMail), MailManager>();
Clear();
}
}
Thank you,
You can add a constraint to your generic type by declaring an interface:
public interface IManager
{
void getData();
setDefault
Delete
}
Define this constraint in declaration of second class which means that M type should implement IManager interface:
public class MyLEvent<T, M>
where T : class
where M : class, IManager
Then, you can invoke members of your class which defined in the interface:
public class MyLEvent<T, M>
where T : class
where M : class, IManager
{
private M manager;
public MyLEvent()
{
manager.Delete();
}
}
The declaration:
public class MyLEvent<T,M> where T : class where M : class
{
...
}
...defines a generic type that is used to create concrete types when provided with the appropriate type parameters. You cannot use generic types directly, you can only use them to create concrete types which can then be used.
For example, the List<T> generic type defines structure and code that can be used to create a variety of concrete types depending on the type parameter you use. List<string> is a concrete type created from the List<T> generic type.
In the case of your MyLEvent generic, there are two type parameters: T and M. You need to specify both of those to create a concrete type that can be used.
In your MyListView class you define the MyLEvnt field like this:
internal MyLEvent<Type,Type> MyLEvnt { get; set; }
This defines the MyLEvnt field as an instance of the concrete type MyLEvent<Type, Type>. Note that Type is a class that is used to access information about types. In this usage it is not a way to avoid supplying a type parameter, it is a type parameter.
In your third class you then do this:
MAILV.MyLEvnt = new MyLEvent<typeof(InvMail), MailManager>();
Even when we take the typeof() out of it, this will fail because you are attempting to assign an instance of MyLEvent<InvMail, MailManager> to a field of type MyLEvent<Type, Type>. These are different types, just as List<string> is different from List<int>.
You need to read the MSDN articles on Generics. These explain the details of how generics work and give you a lot of examples of how to use them and why.
Thank you so much for supporting. And i got one solution for this....
This is my previous 1st class
public class MyListView : ListView
{
public UserControl uc { get; set; }
internal MyLEvent<Type,Type> MyLEvnt { get; set; }
public MyListView()
{
PreviewKeyDown += new KeyEventHandler(MyListView_PreviewKeyDown);
}
private void MyListView_PreviewKeyDown(object sender,KeyEventArgs e)
{
ListView view = sender as ListView;
var item = view.SelectedItem;
if (item != null)
{
string str = item.GetType().Name;
if (e.Key == Key.Delete)
{
MyLEvnt.Method(item, "Delete");
}
else if (e.Key == Key.Enter)
{
MyLEvnt.Method(item, "Modify");
uc.GetType().GetProperty("Update").SetValue(uc, 1, null);
MethodInfo mi = uc.GetType().GetMethod("IClear");
mi.Invoke(uc, null);
}
}
}
}
After modified in my level....
public class MyListView : ListView
{
public UserControl uc { get; set; }
public object ML { get; set; }
public MyListView()
{
PreviewKeyDown += new KeyEventHandler(MyListView_PreviewKeyDown);
}
public void Methode<T,M>() where T : class where M : class
{
ListViewEvents<T, M> mn = new ListViewEvents<T, M>();
ML = mn;
}
private void MyListView_PreviewKeyDown(object sender,KeyEventArgs e)
{
ListView view = sender as ListView;
var item = view.SelectedItem;
if (item != null)
{
string str = item.GetType().Name;
if (e.Key == Key.Delete)
{
MethodInfo mi = ML.GetType().GetMethod("Method");
mi.Invoke(ML,new[]{item,"Delete"});
MethodInfo m = uc.GetType().GetMethod("IClear");
m.Invoke(uc, null);
}
else if (e.Key == Key.Enter)
{
MethodInfo m = ML.GetType().GetMethod("Method");
object ob = m.Invoke(ML, new[] { item, "Modify" });
PropertyClass.Properties(uc, ob, 'U');
}
}
}
}
This solution is better working for me. But if is there any wrong with this
please let me guide
Thank you again...
I have a Website which has several aspx pages that derives from a PageBase class. For example one of that is below:
public partial class Pages_Home_Default : PageBase
{
}
In some of these pages, I would like to prevent access UNLESS logged in. I can get whether client is logged in or not in my PageBase with a IsMember property.
I would like to use attibutes to achive that. For example:
[AuthenticationRequired(true)]
public partial class Pages_Home_Default : PageBaseList
{
}
[AttributeUsage(AttributeTargets.Class)]
public class AuthenticationRequired : Attribute
{
public AuthenticationRequired(bool isMemberRequired)
{
Value = isMemberRequired;
}
public bool Value { get; private set; }
}
and in the PageBase for example:
protected override void OnPreInit(EventArgs e)
{
//Retrieve the AuthenticationRequired attribue value and if not authenticated Redirect client to a login page if logged in, continue displaying the page
}
I also found this to get and read the attribute
System.Reflection.MemberInfo info = typeof(Pages_Home_Default);
object[] attributes = info.GetCustomAttributes(true);
But this is not practical when you want to do it on the BASE class instead of the DERIVED one.
Can this be done?
Thank you very much
If your using MVC, there's an att for that - AuthorizeAttribute.
If your using WebForms then you don't need to use an attribute, you can control this from the web.config using the authorization element.
Why don't you check it in the attribute itself?
[AttributeUsage(AttributeTargets.Class)]
public class AuthenticationRequired : Attribute
{
public AuthenticationRequired(bool isMemberRequired)
{
if(isMemberRequired && !HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsAuthentication.RedirectToLoginPage();
}
}
}
Ok. I combined the code I have given earlier with a simple line from other sources and here is the code I came up with:
[AttributeUsage(AttributeTargets.Class)]
public class AuthenticationRequired : Attribute
{
public AuthenticationRequired(bool isMemberRequired)
{
Value = isMemberRequired;
}
public bool Value { get; private set; }
}
public class Utility
{
public static T GetCustomAttribute<T>(Type classType) where T : Attribute
{
object Result = null;
System.Reflection.MemberInfo Info = classType;
foreach (var Attr in Info.GetCustomAttributes(true))
{
if (Attr.GetType() == typeof(T))
{
Result = Attr;
break;
}
}
return (T)Result;
}
}
public class PageBase : System.Web.UI.Page
{
protected override void OnPreInit(EventArgs e)
{
AuthenticationRequired AttrAuth = Utility.GetCustomAttribute<AuthenticationRequired>(this.GetType());
if (AttrAuth != null && AttrAuth.Value)
{
if(!IsMember)
HttpContext.Current.Response.Redirect("Membership.aspx");
}
}
}
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;
language specific (however, if you need a language please use C++/C# or Javascript). I trying to figure out how I would go about doing this, and how I would access the child objects from a parent object.
Say I have the following classes, and these are not written properly etc... :
Class: roomContainer (container of objects)
Class: Table (base class for a table, contains property of maximum-seats, current-number-of-seats, array of seats )
Class: Desk (extends Table, contains property for maximum draws, array of draws )
Class: seat (base class for seats, contains property of maximum-legs, arm-rest, back-rest)
Class: couch (extends seat, adds property maximum seats)
If I create an instance of roomContainer, and add within it's container a table, couch. Within the table I create multiple seats (or chairs), and a desk.
How would I be able to access the property of child objects property, when the parent has a container of different objects. I.e the roomContainer Container of objects, one of them is a table, and a desk - where the desk has different properties and an array of draws etc.. ?
You're looking for something called the Composite Design Pattern. This allows you to nest objects (as you described), and hold references to both the parent and the children (though some implementations do no maintain a parent reference - this is optional).
Here is an example implementation using your schema:
public static class Program // the supporting class definitions are below
{
public static void Main()
{
// create a root container
var room = new RoomContainer();
// create a child
var table = new Table(room, 4);
// put the table in the room
room.Add(table);
MakeMess(room);
}
// to show you how to access the properties
// if you don't already have a reference:
public static void MakeMess(RoomContainer room)
{
if(room == null)
{
throw new ArgumentNullException("room");
}
var seats = room.GetChildren<Table>().First().Seats.ToArray();
for (int index = 0; index < seats.Length; index++)
{
Console.WriteLine("You have kicked over Seat #{0}",(index+1).ToString());
}
}
}
// This is the base class of the components and provides the core functionality.
// You will want to make this object's interface minimal, so that the logic
// is consistent with all its children (without knowing what they might be in advance)
public abstract class Component
{
private readonly IList<Component> _children;
private readonly Component _container;
protected Component(Component container)
{
_container = container;
_children = new Component[] { };
}
public bool IsRoot { get { return _container == null; } }
public abstract bool IsContainer { get; }
public virtual void Add(Component component)
{
if (component == null)
{
throw new ArgumentNullException("component");
}
if (!IsContainer)
{
throw new NotSupportedException("Add is not supported by leaf components");
}
_children.Add(component);
}
public IEnumerable<T> GetChildren<T>()
where T: Component
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children.OfType<T>();
}
public IEnumerable<Component> Children
{
get
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children;
}
}
}
public class RoomContainer : Component
{
public RoomContainer() : base(null)
{
}
public override bool IsContainer { get { return true; } }
}
public class Table : Component
{
private readonly int _maximumSeatCount;
public Table(Component container, int maximumSeatCount) : base(container)
{
_maximumSeatCount = maximumSeatCount;
}
public override bool IsContainer { get { return true; } }
protected virtual bool CanAdd(Component component)
{
return component is Seat && MaximumSeatCount > CurrentSeatCount;
}
public override void Add(Component component){
if(CanAdd(component)){
base.Add(component);
}
else
{
throw new NotSupportedException("The component was an invalid child of Table and could not be added.");
}
}
public int MaximumSeatCount { get { return _maximumSeatCount; } }
public int CurrentSeatCount { get { return Seats.Count(); } }
public IEnumerable<Seat> Seats { get { return Children.OfType<Seat>(); } }
}
public class Seat : Component
{
// you can restrict the constructor to only accept a valid parent
public Seat(Table table) : base(table)
{
}
public override bool IsContainer
{
get { return false; }
}
}
If the all share common methods, for example Render(), Update(), SaveDetails(int Id), LoadDetails(int Id) then you could make them all inherit from a base class, or all impliment a common interface. This would remove the need for casting (below) when calling a common method (or accessing a common property).
To access properties unique to the derived class you would check the type of the child object, then cast the child object to access the property.
EDIT: Example:
foreach(Object obj in Room.ChildObjects)
{
if(obj is Desk)
{
Desk DeskObj = obj as Desk; // Cast the object reference as a desk.
DeskObj.MaxDraws = 50; // It's a big desk!
DestObj.Draws[1] = new Draw(); // ......
}
}
Something like this:
IEnumerable<Desk> desks = roomContainer.OfType<Desk>();
//Iterate and do stuff.
IEnumerable<Table> tables = roomContainer.OfType<Table>();
//Iterate and do stuff.