我有.net 3.5,我想制作一个通用的方法。我该如何重构这段代码?
case (int)Enums.SandwichesHoagies.Cheeses:
if (this.Cheeses.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
{
var newCheese = new Cheese
{
Id = product.ProductId,
Name = product.Name,
PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
};
this.Cheeses.Add(newCheese);
}
else
{
foreach (var cheese in this.Cheeses.Where(cheese => cheese.Id == product.ProductId))
{
this.Cheeses.Remove(cheese);
break;
}
}
foreach (var cheese in Cheeses) cheese.Type = string.Empty;
if (this.Cheeses.Count > 0) Cheeses.First().Type = "Cheeses:";
break;
case (int)Enums.SandwichesHoagies.Meats:
if (this.Meats.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
{
var newMeat = new Meat
{
Id = product.ProductId,
Name = product.Name,
PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
};
this.Meats.Add(newMeat);
}
else
{
foreach (var meat in this.Meats.Where(meat => meat.Id == product.ProductId))
{
this.Meats.Remove(meat);
break;
}
}
foreach (var meat in Meats) meat.Type = string.Empty;
if (this.Meats.Count > 0) Meats.First().Type = "Meats:";
break;
答案 0 :(得分:5)
假设有两件事:
Meat
和Cheese
继承自Ingredient
或实施IIngredient
Meats
和Cheeses
个集合为IList<T>
我们走了:
private void OuterMethod()
{
switch(something)
{
case (int)Enums.SandwichesHoagies.Cheeses:
HandleCase(product, this.Cheeses);
break;
case (int)Enums.SandwichesHoagies.Meats:
HandleCase(product, this.Meats);
break;
}
}
private void HandleCase<T>(Product product, List<T> list) where T : Ingredient, new()
{
if(list.Any(i => i.Id == product.ProductId))
{
list.Add(new T {
Id = product.ProductId,
Name = product.Name,
PriceValue = product.PriceValue ?? 0.0;
});
}
else
{
list.RemoveAll(i => i.Id == product.ProductId);
}
//NOTE: this part seems like a bad idea. looks like code smell.
foreach (var i in list)
{
i.Type = string.Empty;
}
if (list.Count > 0)
{
list.First().Type = "Cheeses:";
}
}
答案 1 :(得分:3)
初看起来,您可以访问一些常用属性Id, Name, PriceValue, and Type
。这看起来像是我的基类或接口。有了它,您可以从将代码重构为方法
void YourMethod<T>(List<T> list, Product product) where T : IProduct, new()
// IProduct being your interface or base class
在这种情况下,在您引用this.Meats
或this.Cheeses
的情况下,您会改为引用list
,以及您引用Meat
或{{1你只需要引用Cheese
。
了解你能走多远,并进一步重构。
答案 2 :(得分:1)
在不知道所使用的类型(和基本类型/接口)的情况下,很难知道您的确切要求。我假设你正在使用某种ORM,无论如何都要吐出部分类。
使这个易于使用的第一个要求是Meat和Cheese共享一个通用接口(或抽象类)。这应该是基本的东西。
interface IProduct {
int Id { get; set; }
String Name { get; set; }
Double PriceValue { get; set; }
}
假设使用了部分类,可以很容易地扩展您的类以使用此接口。
partial class Cheese : IProduct { }
我觉得有趣的是,你有一种不同类型的产品,它有不同的字段名称,但功能几乎相同。你是否应该保持名称与上面的接口相同,并使其也从界面派生?无论如何,假设你拥有的是这样的东西。
class Product {
int ProductId { get; set; }
String Name { get; set; }
Price? Price { get; set; }
}
您要做的第一件事是使用工厂模式来创建特定产品。
public class ProductFactory {
public T Create<T>(Product product)
where T : IProduct, new() {
return new T {
Id = product.ProductId,
Name = product.Name,
PriceValue = product.Price.HasValue
? (double)product.Price.Value
: 0.00
};
}
}
new()
约束要求在Cheese和Meat类中使用无参数构造函数。我认为这没问题。您只需致电.Create<Cheese>(product);
接下来的部分,我需要假设您的奶酪和肉类对象(或属性),也共享一个公共类(ICollection<IProduct>
),或者您可以根据特定需要定义自己的。
public class ProductCollection : ICollection<IProduct> { ... }
检查产品是否存在的通用方法
Boolean ContainsProduct<T>(ProductCollection<T> collection, Product product)
where T : IProduct {
return collection.Where(x => x.Id == product.Id).SingleOrDefault != null;
}
我对你在foreach循环中调用.Remove
的想法持怀疑态度。修改集合可能会导致用于循环遍历它的枚举器出现问题。如果这是一个问题,我会找到一个更好的方法。