[英]Get the declared variable name in a class
我想做这样的事情 - 在那里我捕获对象内部的原始声明对象变量名称。
public class Foo
{
private string _originalDeclarer;
public Foo(string originalDeclarer=nameof(this))
{
_originalDeclarer = originalDeclarer;
}
public string OriginalDeclarer
{
get => _originalDeclarer;
set => _originalDeclarer = value;
}
}
public static class Bar
{
public static void CreateFoos()
{
Foo GreenFoo = new Foo();
Foo BlueFoo = new Foo();
Console.WriteLine(GreenFoo);
Console.WriteLine(BlueFoo);
//Expected output
// "GreenFoo"
// "BlueFoo"
}
}
以上可以理解是行不通的,我知道变量名没有存储在运行时元数据中,所以这个问题的一般答案是它无法完成。
也就是说,研究使我找到了几种解决方法,我正在寻找最好的方法。
这个问题很好地完成了提案:
class Self
{
public string Name { get; }
public Self([CallerMemberName] string name = null)
{
this.Name = name;
}
}
然后:
class Foo
{
private Self me = new Self(); // Equivalent to new Self("me")
public void SomeMethod()
{
// Can't use the default here, as it would be "SomeMethod".
// But we can use nameof...
var joe = new Self(nameof(joe));
}
}
我还没有测试以上是否有效,但缺点对我来说是有问题的。
我有 - 但我很难找到我在这个问题中找到的较早答案,其中名称在编译时被替换。
如果有人有解决这个问题的方法(即使它慢得可怕)或者知道编译时替换的方式,我会非常感兴趣。
如果我可以在方法中停止实例化,上述建议的解决方法对我有用。
编辑上下文这里是我使用普通枚举的示例 - 我宁愿用我自己的强类型类型替换枚举:ConfiguredDatabase 是一个枚举。
private Result<DatabaseConnectionStatus> TestDatabase(ConfiguredDatabase database)
{
SqlDataAccessLayer sqlDataAccessLayer = DetailsStore.DataAccessLayers.TryGetbyUId(database.ToString());
if (sqlDataAccessLayer.ConnectionDetails.DataSource == string.Empty)
{
return Result.Failed($"Database connection is not configured for {database}", DatabaseConnectionStatus.NoConnectionConfigured);
}
}
查看您的最后一次添加,我不建议使用枚举类型来确定您的数据库。 如果您的枚举类型在稍后阶段删除了值,则会出现问题,例如
enum ConfiguredDatabase
{
Database1,
// Database2,
Database3
}
现在 Database3 的值与过去 Database2 的值相同。 如果您为每个分配固定值,那么仍然可以在您的调用代码中使用分配给 Database2 的值!
相反,我建议通过将接口传递给具体的类类型来坚持一些依赖注入原则。
例如,沿着这些路线的东西。
public interface IConfiguredDatabase
{
string ConnectionString;
}
public Database1 : IConfiguredDatabase
{
public Database1
{
ConnectionString = "Database One";
}
public string ConnectionString{get;set;}
}
public Database2 : IConfiguredDatabase
{
public Database1
{
ConnectionString = "Database Two";
}
public string ConnectionString{get;set;}
}
private Result<DatabaseConnectionStatus> TestDatabase(IConfiguredDatabase database)
{
SqlDataAccessLayer sqlDataAccessLayer = DetailsStore.DataAccessLayers.TryGetbyUId(database.ConnectionString);
if (sqlDataAccessLayer.ConnectionDetails.DataSource == string.Empty)
{
return Result.Failed($"Database connection is not configured for {database.ConnectionString}", DatabaseConnectionStatus.NoConnectionConfigured);
}
}
然后在其他地方你称之为:
using (var d = new Database1()
{
var result = TestDatabase(d);
...
}
我知道我的示例并不完全适合您的代码,但我希望它能让您了解我的建议。
如果您确实需要使用反射来确定您的调用属性是什么,那么我建议您采用以下模式。 我在 MVVM 中将它用于 ViewModel 类,因此使用 OnPropertyChanging 和 OnPropertyChanging 事件,但我相信您会明白这个想法。
您可以调整 BaseClass.SetProperty 以调用其他代码或引发事件以满足您的需要。
public class BaseClass
{
/// <summary>
/// Worker function used to set local fields and trigger an OnPropertyChanged event
/// </summary>
/// <typeparam name="T">Parameter class</typeparam>
/// <param name="backingStore">Backing field referred to</param>
/// <param name="value">New value</param>
/// <param name="propertyName">Property that this value is applied to </param>
/// <param name="onChanged">Event handler to invoke on value change</param>
/// <param name="onChanging">Event handler to invoke on value changing</param>
/// <returns></returns>
protected bool SetProperty<T>(
ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null,
Action<T> onChanging = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value)) return false;
onChanging?.Invoke(value);
OnPropertyChanging(propertyName);
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
/// <summary>
/// INotifyPropertyChanging event handler
/// </summary>
public event PropertyChangingEventHandler PropertyChanging;
/// <summary>
/// INotifyOnPropertyChanging implementation
/// </summary>
/// <param name="propertyName">Class property that is changing</param>
protected void OnPropertyChanging([CallerMemberName] string propertyName = "")
{
var changing = PropertyChanging;
changing?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}
/// <summary>
/// INotifyPropertyChanged event handler
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// INotifyPropertyChanged implementation
/// </summary>
/// <param name="propertyName">Class property that has changed</param>
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
changed?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SomeClass : BaseClass
{
private int _propertyOne;
private string _propertyTwo;
public int PropertyOne
{
get=> return _propertyOne;
set=> SetProperty(ref _propertyOne, value);
}
public int PropertyTwo
{
get=> return _propertyOne;
set=> SetProperty(ref _propertyTwo, value);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.