[英]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.