How do I make a generic SearchDTO which can be used as a template for any Search?
It should have any filter and other general information like TotalRecords, Sort Order, Pages, Start Row, etc
public abstract class SearchDTO
{
public object Id { get; set; }
public IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
And any Search Object looks like.
public class EmployeeSearchDTO:SearchDTO
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
But I get the following error in IList<T> property:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?).
How could I specify like returing a List of any objects and I can create other property like
public long TotalRecords
{
get
{
return SearchResults.Count;
}
set;
}
Is there any best approach other than this to solve this?
You need to specify T as type parameter on your class:
public abstract class SearchDTO<T>
Then when you will inherit from it - you should either provide concrete type instead of type parameter:
public class EmployeeSearchDTO : SearchDTO<MyConcreteType>
or successor class should be generic as well:
public class EmployeeSearchDTO<T> : SearchDTO<T>
You need the declaration on the class as well, to know what type T is:
Code for abstract class
public abstract class SearchDTO<T>
{
public object Id { get; set; }
public abstract IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
IList<T> SearchResults must be declare as abstract and override in inherited class.
Code of EmployeeSearchDTOP
public class EmployeeSearchDTO:SearchDTO<Employee>
{
public override IList<Employee> SearchResults { get; set; }
}
Create Employee class and move FirstName & LastName properties in Employee class.
Employee Class
public class Employee
{
public string FirstName {get; set; }
public string LastName {get;set;}
}
Until and unless there is a specific reason for you to use a abstract class what you want can be achieved by simply using a template class:
public class SearchDTO<T>
{
public object Id { get; set; }
public IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
For creating object all you need to do is this:
SearchDTO<EmployeeSearchDTO> obj=new SearchDTO<EmployeeSearchDTO>();
And instead of having SearchResults property create a function that would return a list of EmployeeSearchDTO objects, like this:
public IList<T> SearchResults()
{
IList<T> listObj=new List<T>();
//your code here
return listObj;
}
Related
On one hand I have a list of capabilities, for example:
public interface ICapability
{
public string Name { get; }
}
public class RangeCapability<T> : ICapability
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
On the other hand I have a list of requirements
public interface IRequirement
{
public string Name { get; }
}
public class Requirement<T> : IRequirement
{
public string Name { get; set; }
public T Value { get; set; }
}
Both capability list may contain capabilities of different types T and requirement list may contain requirements of different types. The important thing is that if for a given name the underlying types match I should check if value is between min and max (for range class) or in a set like in the example below:
public class Entity
{
List<ICapability> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement> requirements)
{
foreach(var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement .Name);
//how to check if here if types match and if req. within range or in collection?
}
}
}
I am not sure how to match generic types of two different classes and then do the check suitable for the apropriate implementation (is within range/is present in set). Can somebody point me in the right direction how could I make it work?
I believe this is what you're looking for. Make the interfaces generic and also make the Entity class generic.
public interface INamed<T>
{
string Name { get; }
}
public interface ICapability<T> : INamed<T>
{
}
public class RangeCapability<T> : ICapability<T>
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
public interface IRequirement<T> : INamed<T>
{
}
public class Requirement<T> : IRequirement<T>
{
public string Name { get; set; }
public T Value { get; set; }
}
public class Entity<T>
{
List<ICapability<T>> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement<T>> requirements)
{
foreach (var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement.Name);
//how to check if here if types match and if req. within range or in collection?
if(capability is INamed<T>)
{
Console.WriteLine("types match");
}
}
}
}
I have the following construction of classes, here simplified as child classes of a 'mother' class called DataClass, which also contains one simple method:
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public int Count()
{
Type t = typeof(DataClass);
return typeof(DataClass).GetProperties().Length;
}
}
public class PartClass
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
}
public class MemberClass
{
public int versionNum { get; set; }
public SideClass side { get; set; }
}
public class SideClass
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
}
The issue is, I want to refactor the method so that it can give me an accurate counting of all properties found, including the ones in nested or child classes. In the above example, it only counts properties of DataClass, while I wanted it to return 2 for DataClass + 2 for PartClass + 1 for MemberClass + 3 for SideClass, sums up to 8 properties you may set through DataClass.
Can someone help me with this?
You can introduce interface with Count() method
public interface ICountable
{
int Count();
}
And use this interface to mark all types, which properties are participating in Count() calculation.
You can see the generic abstract class to implement this interface below. Generic T parameter is type whose properties need to be calculated. You implement a calculation logic only once and inherit this class where needed. You also go through all of properties, implementing ICountable, to calculate them as well (some kind of recursion)
public abstract class Countable<T> : ICountable
{
public int Count()
{
Type t = typeof(T);
var properties = t.GetProperties();
var countable = properties.Select(p => p.PropertyType).Where(p => typeof(ICountable).IsAssignableFrom(p));
var sum = countable.Sum(c => c.GetProperties().Length);
return properties.Length + sum;
}
}
and inherit it in your classes
public class DataClass : Countable<DataClass>
{
...
}
public class PartClass : Countable<PartClass>
{
...
}
public class MemberClass : Countable<MemberClass>
{
...
}
public class SideClass : Countable<SideClass>
{
...
}
And this is for the test
var dataClass = new DataClass();
var count = dataClass.Count();
It returns 8 as expected
First of all I'm new to C#.
The error I get is:
Additional information: Unable to cast object of type 'UserGUI.MyItems' to type 'CommonBookLib.AbstractItem'.
They are 2 different classes:
public class MyItems
{
public string ItemName { get; set; }
public int CopyNumber { get; set; }
public int Guid { get; set; }
public DateTime? TimePrinted { get; set; }
public string Category { get; set; }
public string SubCategory { get; set; }
public bool? BestSeller { get; set; }
}
and
public class AbstractItem : IPropsDetails
{
public int CopyNumber { get; }
public string ItemName { get; }
public DateTime Time { get; }
public int Guid { get; }
public AbstractItem(int copyNumber, string itemName, DateTime time, int guid)
{
this.CopyNumber = copyNumber;
this.ItemName = itemName;
this.Time = time;
this.Guid = guid;
}
}
It happens when I do:
AbstractItem myItemsList = (AbstractItem)LibraryList.SelectedItem;
logicManager.Remove(myItemsList);
Well, as you can see, I have MyItems which are responsible for the DataBindings in my GUI and AbstractItem which responsible for implementing an addition operation to where my data is saved.
Since I did not managed my code well I got into this situation and I really do not want to change MyItems (delete and recode AbstractItem).
How can I Convert the two?
By the way, I know AbstractItem has only 4 properties while MyItems has more.
However, I have children with the exact same properties of AbstractItem.
Any help would be appreciated. Thanks in advance!
Remove fields from the MyItems class that are also present in AbstractItem, and then have MyItems derive from it instead.
You'll have to add a constructor to MyItems that passes the required values to the base constructor, or add an empty constructor to the base class.
public class MyItems : AbstractItem
{
public MyItems(int copyNumber, string itemName, DateTime time, int guid)
:base(copyNumber, itemName, time, guid)
{
}
public DateTime? TimePrinted { get; set; }
public string Category { get; set; }
public string SubCategory { get; set; }
public bool? BestSeller { get; set; }
}
You can make MyItems inherit AbstractItem, or make a method that handle the conversion between them.
You seem to need a mapper more than a cast. Look at AutoMapper or write your own routine as suggested by habibhassani. Also, Grant's answer is very good.
But your question was about casting so here I show how you can implement a casting operator so that your cast would work. This is not a technique you should reach for lightly. It puts a dependency on AbstractItem directly in MyItems and it is not the most discoverable pattern for maintainers of your code.
public class MyItems
{
public string ItemName { get; set; }
public int CopyNumber { get; set; }
public int Guid { get; set; }
public DateTime? TimePrinted { get; set; }
public string Category { get; set; }
public string SubCategory { get; set; }
public bool? BestSeller { get; set; }
public static explicit operator AbstractItem(MyItems myitems)
{
return new AbstractItem(myitems.CopyNumber, myitems.ItemName, myitems.TimePrinted, myitems.Guid);
}
}
A couple more observances. Naming your class AbstractItem is confusing, it implies that it is actually abstract but it is not.
Guid is a poor name for a property because it is already a Type. You have something named Guid that is an int - confusing.
I have the following in my Api Controller:
[AcceptVerbs("POST")]
public Model.ViewModel.ContactSaveRequest DeleteMethod(Model.ViewModel.ContactSaveRequest methodsToDelete)
{
var contactMethodRepos = new Model.ContactMethodRepository();
foreach (var contactMethod in methodsToDelete)
{
contactMethodRepos.Delete(contactMethod);
return contactMethod;
}
}
This is my class defining a contact method
[JsonProperty("id")]
public int ID { get; set; }
[JsonProperty("contactID")]
public int ContactID { get; set; }
[JsonProperty("typeOfContactMethodID")]
public int TypeOfContactMethodID { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("methodsToDelete")]
public IEnumerable<ContactMethod> methodsToDelete { get; set; }
ContactSaverequest class:
public class ContactSaveRequest
{
[JsonProperty("contact")]
public Contact Contact { get; set; }
[JsonProperty("contactMethods")]
public IEnumerable<ContactMethod> ContactMethods { get; set; }
}
I have an array which pushes methods into it to be deleted (methodsToDelete). I am trying to use the Delete method on the array but keep getting the issue that contactSaveRequest doesn't contain a definition for GetEnumerator.
It sounds like you just want to use:
foreach (var contactMethod in methodsToDelete.ContactMethods)
You can't iterate over a ContactSaveRequest, but you can iterate over the IEnumerable<ContactMethod> that is returned by the ContactMethods property.
Try to implement IEnumerable interface like this
public class ContactSaveRequest : IEnumerable
{
}
I have an application that has a concept of a Venue, a place where events happen. A Venue has many VenueParts. So, it looks like this:
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
A Venue can be a GolfCourseVenue, which is a Venue that has a Slope and a specific kind of VenuePart called a HoleVenuePart:
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public virtual ICollection<HoleVenuePart> Holes { get; set; }
}
In the future, there may also be other kinds of Venues that all inherit from Venue. They might add their own fields, and will always have VenueParts of their own specific type.
Here are the VenuePart classes:
public abstract class VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get { return "Hole"; } }
public int Yardage { get; set; }
}
My declarations above seem wrong, because now I have a GolfCourseVenue with two collections, when really it should just have the one. I can't override it, because the type is different, right? When I run reports, I would like to refer to the classes generically, where I just spit out Venues and VenueParts. But, when I render forms and such, I would like to be specific.
I have a lot of relationships like this and am wondering what I am doing wrong. For example, I have an Order that has OrderItems, but also specific kinds of Orders that have specific kinds of OrderItems.
Update: I should note that these classes are Entity Framework Code-First entities. I was hoping this wouldn't matter, but I guess it might. I need to structure the classes in a way that Code-First can properly create tables. It doesn't look like Code-First can handle generics. Sorry this implementation detail is getting in the way of an elegant solution :/
Update 2: Someone linked to a search that pointed at Covariance and Contravariance, which seemed to be a way to constrain lists within subtypes to be of a given subtype themselves. That seems really promising, but the person deleted their answer! Does anyone have any information on how I may leverage these concepts?
Update 3: Removed the navigation properties that were in child objects, because it was confusing people and not helping to describe the problem.
Here's one possible option using generics:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
}
Here GolfCourseVenue has the collection VenueParts, which can contain HoleVenueParts or super classes HoleVenueParts. Other specializations of Venue would restrict VenueParts to containing VenueParts specific to that venue.
A second possibility is pretty much as you had it
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
}
Now GolfCourseVenue has the collection VenueParts, which can contain VenueParts or super classes VenueParts. Here all specializations of Venue can contain any type of VenuePart which may or may not be appropriate.
In answer to your comment about covariance, I would propose something like this:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get{return "I'm a hole venue"; } }
}
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public abstract ICollection<VenuePart> VenueParts { get; }
}
public class GolfCourseVenue : Venue
{
private ICollection<HoleVenuePart> _holeVenueParts;
public GolfCourseVenue(ICollection<HoleVenuePart> parts)
{
_holeVenueParts = parts;
}
public override ICollection<VenuePart> VenueParts
{
get
{
// Here we need to prevent clients adding
// new VenuePart to the VenueParts collection.
// They have to use Add(HoleVenuePart part).
// Unfortunately only interfaces are covariant not types.
return new ReadOnlyCollection<VenuePart>(
_holeVenueParts.OfType<VenuePart>().ToList());
}
}
public void Add(HoleVenuePart part) { _holeVenueParts.Add(part); }
}
I look forward to the advice of others - but my approach is to use generics in this case. With generics, your GolfCourseVenue's "parts" are strong typed!
...and as I type this everyone else is saying generics too. HOW DO YOU overstackers type so dang fast?!
Anyways, pretending I'm still first -
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public abstract class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
}
Also, as a 2nd option, you could use an interface too, so in case you didn't like the name Parts, you could call it Holes when the derived type is known to be a GolfCourse
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public interface IPartCollection<T> where T : VenuePart
{
ICollection<T> Parts { get; set; }
}
public abstract class Venue<T> : IPartCollection<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
ICollection<HoleVenuePart> IPartCollection<HoleVenuePart>.Parts { get { return base.Parts; } set { base.Parts = value; }}
public virtual ICollection<HoleVenuePart> Holes { get { return base.Parts; } set { base.Parts = value;}}
}
You can use Covariance
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual IEnumerable<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public GolfCourseVenue()
{
List<HoleVenuePart> HoleVenueParts = new List<HoleVenuePart>();
HoleVenueParts.Add(new HoleVenuePart());
VenueParts = HoleVenueParts;
}
}
Assuming HoleVenuePart is inherited from VenuePart
If you remove "set" portions of both collections than it will make more sense: base class provides "all parts" collection, while derived classes have filtered view in addition to base class one.
Note: Depending on your needs making GolfVenue to be specialization generic of Venue<VenuePart> may not work as Venue<Type1> and Venue<Type2> will not have any good base class to work with.
Consider using interfaces instead of base classes as it would allow more flexibility in implementation.
public interface IVenue
{
public int Id { get; }
public string Name { get; }
public virtual IEnumerabe<VenuePart> VenueParts { get; }
}
public interface IGolfCourse : IVenue
{
public virtual IEnumerabe<HoleVenuePart> Holes { get; }
}
Now you can use GolfCourse:Venue from other samples but since it implements interface you can handle it in gnereic way too:
class GolfCourse:Venue<HoleVenuePart>, IGolfCourse {
public virtual IEnumerabe<VenuePart> Holes{ get
{
return VenueParts.OfType<HoleVenuePart>();
}
}
}
class OtherPlace:Venue<VenuePart>, IVenue {...}
List<IVenue> = new List<IVenue> { new GolfCourse(), new OtherPlace() };
Nothe that GolfCourse and OtherPlace don't have common parent class (except object), so without interface you can't use them interchangebly.