I am trying to refactor some code. So the code I am trying to refactor is this
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense)
{
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
Type of items can be List<ApplicationListDto> or List<AdUserApplicationDto> - they both inherit from BaseApplicationDto,
where the common properties are.
Now I want to make a function where I can pass items as a parameter. How should I do this?
I am trying to get rid of the redundant code here
if (isList)
{
if (data.Count <= 0) return;
List<AdUserApplicationDto> userApplicationDto = data;
var items = userApplicationDto;
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense)
{
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
}
else
{
Page<ApplicationListDto> userApplicationDto = data;
if (userApplicationDto.TotalItems <= 0) return;
var items = userApplicationDto.Items;
var userApp = string.Join(",", items.Where(x => x.LicenseType == 1).Select(x => x.GroupName));
var groupApp = string.Join(",", items.Where(x => x.LicenseType == 2).Select(x => x.GroupName));
var totalUsedLicense = GetTotalFreeLicense(schoolCode, userApp, groupApp);
foreach (var item in totalUsedLicense) {
items.FirstOrDefault(x => x.GroupName == item.GroupName).AvailableLicense = items.FirstOrDefault(x => x.GroupName == item.GroupName).TotalLicense - item.Count;
}
}
If you want a method to accept different types of list with a common base type, do this:
public void SomeAction<T>(List<T> list) where T : BaseApplicationDto
{
// ...
}
You use the type of the base class as the type of the list..
public abstract class Common
{
public string CommonString { get; set; }
}
public class B : Common
{
}
public class A : Common
{
}
public class ABConsumer
{
public void DoSomething(List<Common> myList)
{
List<Common> EmptyStrings = myList.Where(x => x.CommonString == string.Empty).ToList();
}
}
You can now access properties of the base class of both classes.
This is simple inheritance.
Edit
It'll require a cast to from any given type: A or B to Common before it can be passed. If casting is an issue another good example using conditional generics can be used as shown in #ikkentims answer.
Related
This below is my code and I want to write a linq query for this three list (Dictionaryfilter,collectionfilter,reffrencefilter) this as are mmy list and want to add when item is selected then add into a SelectedIdList ,Using Linq in c#
SelectedIdList = new List<long>();
foreach (var item in DictionariesFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
foreach (var item in CollectionsFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
foreach (var item in RefrencesFilter)
{
if (item.IsSelected)
{
SelectedIdList.Add(item.DictionaryId);
}
}
It could look something like:
SelectedIdList.AddRange(
DictionariesFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
SelectedIdList.AddRange(
CollectionsFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
SelectedIdList.AddRange(
RefrencesFilter.Where(x=>x.IsSelected).Select(x=>(long)x.DictionaryId)
);
You can do like this.
var results1 = from item in DictionariesFilter
where item.IsSelected
select item.DictionaryId;
selectedList.Add(results1);
and in similar way you could do for the rest of loops.
You could try, if possible:
public interface IFilter
{
bool IsSelected { get; }
int DictionaryId { get; }
}
SelectedIdList = new IFilter[] { DictionariesFilter, CollectionsFilter, ReferencesFilter}
.SelectMany(dic => dic.Where(x => x.IsSelected).Select(x = > (long)x.DictionaryId) )
.ToList();
One way of doing this is to simply use Where and Concat.
SelectedIdList = DictionariesFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId)
.Concat(CollectionsFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId))
.Concat(RefrencesFilter.Where(x => x.IsSelected).Select(x => (long)x.DictionaryId))
.ToList();
If they have a common interface it could be simplified.
public interface IFilter
{
bool IsSelected { get; }
long DictionaryId { get; }
}
SelectedIdList = DictionariesFilter
.Concat(CollectionsFilter)
.Concat(RefrencesFilter)
.Where(x => x.IsSelected)
.Select(x => x.DictionaryId)
.ToList();
How can I write the below code with is T
public IList<IElement> OfClass(Type type)
{
return list
.Where(o => o.GetType() == type)
.ToList();
}
Something like this:
public IList<IEtabsElement> OfClass(....)
{
return list
.Where(o => o is ...)
.ToList();
}
UPDATE
This is my solution, so far. Is it okay?
public IList<IElement> OfClass<T>()
{
return list
.Where(o => o is T)
.ToList();
}
You can create a generic method instead:
public IList<T> OfClass<T>()
{
return list
.Where(o => o.GetType() == typeof(T))
.ToList();
}
This would work, but is the same as the existing method OfType, for example:
var myvehicles = new List<Vehicle> { new Car(), new Bike()};
var mycars = myvehicles.OfType<Car>();
I was wondering what was the best approach to compare multiple objects that are created and having the state of the objects changed to Inactive (Deleted), while creating history and dependencies.
This also means im comparing past and present objects inside a relational table (MarketCookies).
Id | CookieID | MarketID
The ugly solution i found was calculating how many objects had i changed.
For this purpose lets call the items of the Past: ListP
And the new items: ListF
I divided this method into three steps:
1 - Count both lists;
2 - Find the objects of ListP that are not present in List F and change their state to Inactive and update them;
3 - Create the new Objects and save them.
But this code is very difficult to maintain.. How can i make an easy code to maintain and keep the functionality?
Market Modal:
public class Market()
{
public ICollection<Cookie> Cookies {get; set;}
}
Cookie Modal:
public class Cookie()
{
public int Id {get;set;}
//Foreign Key
public int CookieID {get;set}
//Foreign Key
public int MarketID {get;set;}
}
Code:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
int ListPCount = ListP.Count();
int ListFCount = ListF.Count();
if(ListPCount > ListFCount)
{
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete the Object
}
});
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Object
}
});
}
else if(ListPCount < ListFCount)
{
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Objects
}
});
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete Objects
}
});
}
else if(ListPCount == ListFCount)
{
ListP.Foreach(x =>
{
var ItemExists = ListF.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Delete Objects
}
});
ListF.Foreach(x =>
{
var ItemExists = ListP.Where(y => y.Id == x.Id).FirstOrDefault();
if(ItemExists == null)
{
//Create Objects
}
});
}
}
Without a good, minimal, complete code example that clearly illustrates the question, it's hard to know for sure what even a good implementation would look like, never mind "the best". But, based on your description, it seems like the LINQ Except() method would actually serve your needs reasonably well. For example:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
foreach (var item in ListP.Except(ListF))
{
// set to inactive
}
foreach (var item in ListF.Except(ListP))
{
// create new object
}
}
This of course assumes that your objects have overridden Equals() and GetHashCode(). If not, you can provide your own implementation of IEqualityComparer<T> for the above. For example:
// General-purpose equality comparer implementation for convenience.
// Rather than declaring a new class for each time you want an
// IEqualityComparer<T>, just pass this class appropriate delegates
// to define the actual implementation desired.
class GeneralEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> _equals;
private readonly Func<T, int> _getHashCode;
public GeneralEqualityComparer(Func<T, T, bool> equals, Func<T, int> getHashCode)
{
_equals = equals;
_getHashCode = getHashCode;
}
public bool Equals(T t1, T t2)
{
return _equals(t1, t2);
}
public int GetHashCode(T t)
{
return _getHashCode(t);
}
}
Used like this:
public void UpdateMarket (Market Market, int Id)
{
var ListP = MarketCookiesRepository.GetAll()
.Where(x => x.MarketID == Id && Market.State != "Inactive").ToList();
var ListF = Market.Cookies.ToList();
IEqualityComparer<Cookie> comparer = new GeneralEqualityComparer<Cookie>(
(t1, t2) => t1.Id == t2.Id, t => t.Id.GetHashCode());
foreach (var item in ListP.Except(ListF, comparer))
{
// set to inactive
}
foreach (var item in ListF.Except(ListP, comparer))
{
// create new object
}
}
First Thing's First I have a class to manipulate some data through a linq variable:
public class Result
{
public bool LongerThan10Seconds { get; set; }
public int Id { get; set; }
public DateTime CompletionTime { get; set; }
}
Then in a Separate class I'm using this to grab info from a linq var
using (var data = new ProjectEntities())
{
Result lastResult = null;
List<Result> dataResults = new List<Result>();
foreach(var subResult in data.Status.Select(x => x.ID).Distinct().Select(Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time)))
{
if (lastResult != null)
{
if (subResult.CompletionTime.Subtract(lastResult.CompletionTime).Seconds > 10)
dataResults.Add(subResult);
}
lastResult = subResult;
}
however I get the error:
Linq.IOrderedQueryAble does not contain a definition for 'CompletionTime' and no Extension method 'CompletionTime' accepting a first argument of type 'System.Linq.IOrderedQueryable.
Is anyone able to provide a solution to get around this would be much appreciated been trying to figure it out for a while but seems a bit difficult in terms of a DateTime Variable.
Your problem is that subResult holds an IOrderedQueryable (presumably an IOrderedQueryable<Result>) rather than a Result.
You have this in the foreach: var subResult in data.Status.Select(x => x.ID).Distinct().Select(Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time)). Notice what's inside the Select: Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time). That will return an IOrderedQueryable<T>, not a T (where T is whatever type is in the data.Status collection).
You need to either get a single value out of that IOrderedQueryable, using First() or some similar method, like this:
var subResult in data.Status.Select(x => x.ID).Distinct().Select(Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time).First())
... or flatten your IEnumerable<IQueryable<T>> to an IEnumerable<T>:
var subResult in data.Status.Select(x => x.ID).Distinct().SelectMany(Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time))
Edit: You may also be having an issue where C# is uncertain what type the var subResult is. If they're all Result type objects, try replacing var subResult with Result subResult.
Looks like you have to use SelectMany instead your second Select method call
data.Status.Select(x => x.ID).Distinct()
.SelectMany(Id => data.Status.Where(x => x.ID == Id).OrderBy(x => x.Time))
Hello i got some method that generating where statment programmatically how can i move where generation to other class method anyone can help ?
public static List<MME.Objects.TypedLists.InvoiceList> GetList(List<MMPFramework.SearchParameter> parameter)
{
MME.Objects.Invoice Invoice = null;
MME.Objects.Contractor Contractor = null;
MME.Objects.Contract Contract = null;
MME.Objects.TypedLists.InvoiceList invoiceList= null;
var t = MME.DAL.NhSessionHelper.GetCurrentSession().QueryOver<MME.Objects.Invoice>(() => Invoice);
foreach (var searchParameter in parameter)
{
if(searchParameter.Expression == "Like")
{
t.Where(Restrictions.Like(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Eq")
{
t.Where(Restrictions.Eq(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Between")
{
t.Where(Restrictions.Between(searchParameter.PropertyName, searchParameter.ObjectValueLo,searchParameter.ObjectValueHi));
}
else if(searchParameter.Expression == "Gt")
{
t.Where(Restrictions.Gt(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else if (searchParameter.Expression == "Lt")
{
t.Where(Restrictions.Lt(searchParameter.PropertyName, searchParameter.ObjectValueLo));
}
else
{
//todo more
}
//t.Where(Restrictions.Eq(searchParameter.PropertyName, searchParameter.ObjectValue));
}
t.JoinQueryOver(() => Invoice.Contractor, () => Contractor, JoinType.LeftOuterJoin)
.JoinQueryOver(() => Invoice.Contract, () => Contract, JoinType.LeftOuterJoin)
.Select(Projections.Property(() => Invoice.Id).WithAlias(() => invoiceList.Id),
Projections.Property(() => Invoice.Number).WithAlias(() => invoiceList.InvoiceNumber),
Projections.Property(() => Contractor.Name).WithAlias(() => invoiceList.ContractorName),
Projections.Property(() => Contract.Number).WithAlias(() => invoiceList.ContractNumber)
)
.TransformUsing(Transformers.AliasToBean<MME.Objects.TypedLists.InvoiceList>());
return t.List<MME.Objects.TypedLists.InvoiceList>().ToList();
}
I've tried with this but it seems to not work.... Hope someone was doing something and can help me to handle with it.
public class BaseList
{
public object WhereGenerator(object ob)
{
QueryOver Ded = ob as QueryOver;
return null;
}
}
foreach (var restriction in BaseList.Createrestrictions(parameter))
{
t.Where(restriction);
}
public class BaseList
{
public IEnumerable<AbstractCriterion> Createrestrictions(List<MMPFramework.SearchParameter> parameter)
{
return parameter.Select(ToCritieria);
}
private AbstractCriterion ToCritieria(SearchParameter searchParameter)
{
if(searchParameter.Expression == "Like")
{
return Restrictions.Like(searchParameter.PropertyName, searchParameter.ObjectValueLo);
}
else ...
}
}