我有一种方法可以将粘贴复制到许多类中。该方法将模型合并到IdNameViewModel中。如何使用此方法创建一个类,以便可以在存储库模型中传递该类并获取该模型的IdName列表?
注意:ProjectValue是例如我要传递的模型/类,但实际上它可以是包含id和name属性的任何模型/类。
private IdNameVM HydrateEntityToVM(ProjectValue projectValue)
{
if (projectValue == null) return null;
return new IdNameVM()
{
Id = projectValue.Id,
Name = projectValue.Name
};
}
这是我根据以下答案得出的结论:
public class GenericHydrateIdName<TModel> where TModel : INameId
{
public IdNameVM HydrateEntityToVM(TModel model)
{
if (model == null) return null;
return new IdNameVM()
{
Id = model.Id,
Name = model.Name
};
}
}
}
请注意,如果有人在追随,上面的类导致太多的工作,并且违反了“清洁代码原则”。我在下面使用了扩展方法。
答案 0 :(得分:2)
基本上,我可以看到的最好的类型安全方式是使用接口。
private pickupRequest = new BehaviorSubject<boolean>(false);
public pickupStatus = this.pickupRequest.asObservable();
changePickupStatus(value: boolean) {
this.pickupStatus.emit(value);
}
constructor(public http: HttpClient) {
//console.log('Hello PickuprequestProvider Provider');
}
您可以在每个要使用它的类中使用此接口。根据您当前的用法,我建议使用扩展功能
interface INameId
{
int Id { get; set; }
string Name { get; set; }
}
如果您不想将接口添加到所有模型中,则可以使用反射(但请注意,这确实很慢)。
更新
正如Marcus所指出的,在这种情况下,在函数中使用泛型没有实际意义。您可以使用直接使用该接口的static class VMExtensions
{
public static IdNameVM HydrateEntityToVM<TModel>(this TModel model)
where TModel : INameId
{
if (model == null) return null;
return new IdNameVM()
{
Id = model.Id,
Name = model.Name
};
}
// update: without generics as Marcus Höglund pointed out
public static IdNameVM HydrateEntityToVM2(this INameId model)
{
if (model == null) return null;
return new IdNameVM()
{
Id = model.Id,
Name = model.Name
};
}
static void Test()
{
var model = new ProjectValue();
var model2 = new AnotherModel();
var viewModel = model2.HydrateEntityToVM();
var viewModel2 = model2.HydrateEntityToVM();
}
}
实现。但是,在将来,如果您想使用类似HydrateEntityToVM2
之类的东西,以便仍然可以在需要时访问原始模型,则使用泛型的IdNameVM<TModel>
函数将很有帮助。
答案 1 :(得分:0)
这些是C#的基础。看看这个link
class MyClass<T> where T : ProjectValue
{
private IdNameVM HydrateEntityToVM(T projectValue)
{
if (projectValue == null) return null;
return new IdNameVM()
{
Id = projectValue.Id,
Name = projectValue.Name
};
}
}
如果您不知道模型的抽象(但请注意,此方法可以使用任何包含id和name公共属性的对象),请尝试以下操作:
public void SomeGenericMethod<T>(T model) where T : class
{
if (model == null) return null;
var propId = model.GetType().GetProperty("id");
var propName = model.GetType().GetProperty("name");
if (propId == null || propName == null)
return;
return new IdNameVM()
{
Id = model.Id,
Name = model.Name
};
}
答案 2 :(得分:0)
创建通用方法时,必须牢记一些规则
让我们以上述示例为例:您需要一个名称为HydrateEntityToVM
的通用方法。第一步是方法的声明语法以及从T类型的Strong Type进行对象强制转换。
这里要注意的一点是,您正在传递T类型,并且希望结果始终为IdNameVM类,那么您的实现应为:
//The Method declaration of T type
private IdNameVM HydrateEntityToVM<T>(T projectValue)
{
//Checking whether the object exists or not
//if null than return the default value of IdNameVM
if(projectValue == null) return default(IdNameVM);
//Checking if we are supporting the implementation or not for that class
//In your case YourStrongTypeClass is ProjectValue Class
if(projectValue is YourStrongTypeClass)
{
//Casting the T object to strong type object
var obj = projectValue as YourStrongTypeClass;
return new IdNameVM()
{
Id = obj.Id,
Name = obj.Name
};
}
else
{
//The else statement is for if you want to handle some other type of T implementation
throw new NotImplementedException($"The type {typeof(T)} is not implemented");
}
}
答案 3 :(得分:0)
我喜欢内维尔·纳泽兰(Neville Nazerane)的回答,因为它消除了反思的需要。但是,如果您确实想使用反射来做到这一点,那么即使找不到匹配的Id或Name属性,下面也是一种构造结果的可行方法。
请注意,在此示例中,我没有添加任何有关I和Name属性的类型在T和TResult之间是否匹配的检查。
public static TResult HydrateEntityToVM<T, TResult>(T inputValue, TResult resultValue) where T : class
{
if (inputValue == null || resultValue == null)
return default(TResult);
var idValue = inputValue.GetType().GetProperty("Id").GetValue(inputValue);
var nameValue = inputValue.GetType().GetProperty("Name").GetValue(inputValue);
object instance;
if (resultValue == null)
{
var ctor = resultValue.GetType().GetConstructor(Type.EmptyTypes);
instance = ctor.Invoke(new object[] {});
}
else
{
instance = resultValue;
}
var idProp = instance.GetType().GetProperty("Id");
if (idProp != null)
{
if (idProp.CanWrite)
idProp.SetValue(instance, idValue);
}
var nameProp = instance.GetType().GetProperty("Name");
if (nameProp != null)
{
if (nameProp.CanWrite)
nameProp.SetValue(instance, nameValue);
}
return (TResult) instance;
}