C# Blazor:是否可以使用反射按名称将泛型项绑定到属性?
我正在尝试使用Blazor获得一个通用编辑器模板,该模板绑定到通过反射找到的属性,如下所示:C# Blazor:是否可以使用反射按名称将泛型项绑定到属性?,c#,reflection,binding,blazor,C#,Reflection,Binding,Blazor,我正在尝试使用Blazor获得一个通用编辑器模板,该模板绑定到通过反射找到的属性,如下所示: @typeparam TItem @foreach (var propertyName in FieldsList) { <div> <InputText id="name" @bind-Value="@getBindProperty(propertyName)" /> </div> } @f
@typeparam TItem
@foreach (var propertyName in FieldsList) {
<div>
<InputText id="name" @bind-Value="@getBindProperty(propertyName)" />
</div>
}
@functions {
[Parameter]
public TItem ItemEditModel { get; set; }
public string[] FieldsList {
get {
// get all properties decorated with some custom attribute...
return typeof(TItem).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(MyCustomAttribute))).Select(x => x.Name).ToArray();
}
}
public string getBindProperty(string propName) {
return string.Format("{0}.{1}", nameof(ItemEditModel), propName);
}
}
@foreach (var propertyName in FieldsList) {
<div>
<InputText id="name" @bind-Value="@myContextObject.StrValues[propertyName]" />
</div>
}
@typeparam-TItem
@foreach(FieldsList中的var propertyName){
}
@功能{
[参数]
公共滴度ItemEditModel{get;set;}
公共字符串[]字段列表{
得到{
//获取使用某些自定义属性修饰的所有属性。。。
返回typeof(TItem).GetProperties()。其中(prop=>Attribute.IsDefined(prop,typeof(MyCustomAttribute)))。选择(x=>x.Name).ToArray();
}
}
公共字符串getBindProperty(字符串propName){
返回string.Format(“{0}.{1}”,nameof(ItemEditModel),propName);
}
}
不接受上述内容,因为赋值的左侧必须是变量、属性或索引器
所以我不能通过属性名绑定到属性,所以我继续尝试其他语法,比如
<InputText id="name" @bind-Value="ItemEditModel.propertyName" />
这也不被接受,因为TItem不包含“propertyName”的定义
所有这些都是有意义的——但关键的问题是——是否需要对此做些什么,或者是否不可能通过名称将控件绑定到属性
奖金问题:
如果确实可以这样做,是否有一种方法可以根据属性类型进行切换(通常,只有基本类型,如'string´、'DateTime´、'int´、'double´、'bool´……?如果使用InputText Blazor的组件,则应使用EditForm Blazor的组件对其进行包装 另一种方法可能如下。 @typeparam滴度
@foreach (var propertyName in FieldsList)
{
<div>
<input @bind="PropertyVars[propertyName]" />
</div>
}
<button type="button" @onclick="OnSubmit">Reset</button>
@code {
[Parameter]
public TItem ItemEditModel { get; set; }
public Dictionary<string, string> PropertyVars { get; set; } = new
Dictionary<string, string>();
protected override void OnInitialized()
{
foreach (var propertyName in FieldsList)
{
var propertyInfo = ItemEditModel.GetType().GetProperty(propertyName);
PropertyVars.Add(propertyName,
propertyInfo?.GetValue(ItemEditModel).ToString());
}
}
public string[] FieldsList
{
get
{
return typeof(TItem).GetProperties().Select(x => x.Name).ToArray();
}
}
private void OnSubmit()
{
var tt = PropertyVars;
foreach (var propertyName in FieldsList)
{
var propertyInfo = ItemEditModel.GetType().GetProperty(propertyName);
var uu = PropertyVars[propertyName].GetType();
if (uu == propertyInfo?.PropertyType)
{
propertyInfo.SetValue(ItemEditModel,
Convert.ChangeType(PropertyVars[propertyName], propertyInfo.PropertyType),
null);
}
}
var yy = ItemEditModel;
}
}
@foreach(FieldsList中的var propertyName)
{
}
重置
@代码{
[参数]
公共滴度ItemEditModel{get;set;}
公共字典属性vars{get;set;}=new
字典();
受保护的覆盖无效OnInitialized()
{
foreach(FieldsList中的var propertyName)
{
var propertyInfo=ItemEditModel.GetType().GetProperty(propertyName);
添加(propertyName,
propertyInfo?.GetValue(ItemEditModel.ToString());
}
}
公共字符串[]字段列表
{
得到
{
返回typeof(TItem).GetProperties().Select(x=>x.Name).ToArray();
}
}
私有void OnSubmit()
{
var tt=不动产var;
foreach(FieldsList中的var propertyName)
{
var propertyInfo=ItemEditModel.GetType().GetProperty(propertyName);
var uu=PropertyVars[propertyName].GetType();
if(uu==propertyInfo?.PropertyType)
{
propertyInfo.SetValue(ItemEditModel,
Convert.ChangeType(PropertyVars[propertyName],propertyInfo.PropertyType),
无效);
}
}
var yy=ItemEditModel;
}
}
总结我最终得到的解决方案:
公共类索引属性{
只读操作SetAction;
只读函数GetFunc;
公共IndexedProperty(Func getFunc,Action setAction){
this.GetFunc=GetFunc;
this.SetAction=SetAction;
}
公共TValue this[TIndex i]{
得到{
返回GetFunc(i);
}
设置{
设置动作(i,值);
}
}
}
公共类ReadOnlyIndexedProperty{
只读函数GetFunc;
公共只读索引属性(Func getFunc){
this.GetFunc=GetFunc;
}
公共TValue this[TIndex i]{
得到{
返回GetFunc(i);
}
}
}
公共类WriteOnlyIndexedProperty{
只读操作SetAction;
public WriteOnlyIndexedProperty(操作集操作){
this.SetAction=SetAction;
}
公共TValue this[TIndex i]{
设置{
设置动作(i,值);
}
}
}
IndexedProperty<string, string> _strValues;
[JsonIgnore]
public IndexedProperty<string, string> StrValues {
get {
if (_strValues == null) {
_strValues = new IndexedProperty<string, string>(GetStrValue, SetStrValue);
}
return _strValues;
}
}
private string GetStrValue(string propName) {
// use reflection here to get the property value as string
// --- NOTE: beware of performance here I suggest you take a look at related link
}
private void SetStrValue(string propName, string value) {
// use reflection here to SET the property value from string
// --- NOTE: beware of performance here I suggest you take a look at related link
}
索引属性值;
[JsonIgnore]
公共索引属性值{
得到{
如果(_strValues==null){
_strValues=新的IndexedProperty(GetStrValue,SetStrValue);
}
返回正确值;
}
}
私有字符串GetStrValue(字符串propName){
//在此处使用反射以字符串形式获取属性值
//---注意:注意这里的性能我建议你看看相关链接
}
私有void SetStrValue(字符串propName、字符串值){
//在此处使用反射设置字符串的属性值
//---注意:注意这里的性能我建议你看看相关链接
}
@typeparam TItem
@foreach (var propertyName in FieldsList) {
<div>
<InputText id="name" @bind-Value="@getBindProperty(propertyName)" />
</div>
}
@functions {
[Parameter]
public TItem ItemEditModel { get; set; }
public string[] FieldsList {
get {
// get all properties decorated with some custom attribute...
return typeof(TItem).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(MyCustomAttribute))).Select(x => x.Name).ToArray();
}
}
public string getBindProperty(string propName) {
return string.Format("{0}.{1}", nameof(ItemEditModel), propName);
}
}
@foreach (var propertyName in FieldsList) {
<div>
<InputText id="name" @bind-Value="@myContextObject.StrValues[propertyName]" />
</div>
}
@foreach(FieldsList中的var propertyName){
}
@copycar_am和.这实际上是在创建一个“缓冲区”,在完成后存储/检索这些值,这当然是一个不错的方法。。。你知道这是否可以直接绑定到原始对象吗?好的,基于你的anser,我在基类中添加了一个属性indexor,它返回与上面相同的结果-这让整个魔法发挥了作用。谢谢你的主意!在这里分享另一个有用的资源,为这里的一个非常有用的技巧提供奖励:@neggenbe欢迎您。很高兴能提供帮助,谢谢你的链接,非常感谢helpfull@neggenbe难道你不想用你的结局来回答你自己的问题吗?我发现自己正在尝试做类似的事情。PS:很抱歉格式化,无法正确检测代码。。。