Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

可以注入并使用一些字段吗? #6

Open
xzaxzaazx opened this issue May 29, 2024 · 5 comments
Open

可以注入并使用一些字段吗? #6

xzaxzaazx opened this issue May 29, 2024 · 5 comments

Comments

@xzaxzaazx
Copy link

在注入方法的时候需要一些额外字段的支持,该怎么操作?

@labbbirder
Copy link
Owner

我不太确定你想要额外字段是哪种形式。

如果是元数据意义上的额外成员,那么很遗憾,无法实现,这是任何注入库都在避免实现的功能。btw,这个需求在某些情况下可以使用源生成解决。

如果你只是想通过增加几个变量来影响方法的行为,那么可以使用闭包来实现;如果你希望变量的生命周期关系与一个实际绑定,那么可以通过一个全局字典来实现(小心内存泄漏,同时应避免在unity中使用ConditionalWeakTable)

@xzaxzaazx
Copy link
Author

我想实现类似Auto-Implemented Property的一些功能,我也想过全局字典,如果对static的字段还好说,但如果对每个instance都用字典处理是不是有点复杂?我看到InjectHelper里有注入field的步骤,是否可以做成一些工具开放?

@labbbirder
Copy link
Owner

可否通过例子来说明

@xzaxzaazx
Copy link
Author

xzaxzaazx commented May 30, 2024

例如一个属性

string name=>$"{lastName} {firstName}";

我希望它的getter在第一次调用后固化在一个field里,那样需要额外写一个string的field和一个bool去存储是否第一次调用,我觉得这样写一堆参数很影响代码的直观
于是我希望通过注入达到这样的效果:

[Const]string name=>$"{lastName} {firstName}";

将这个属性注成这样:

string name{get{
     if(!name_loaded_UID)name_data_UID=$"{lastName} {firstName}";
     return name_loaded_UID;
}}
bool name_loaded_UID;
string name_data_UID;

而这需要一个类似于现在InjectionInfo.Create的东西,也许长这样:

public static InjectionInfo CreateField(Type type, string fieldName, Action<FieldInfo> fieldReceiver);

@labbbirder
Copy link
Owner

labbbirder commented May 30, 2024

暴露LowLevel接口是可行的方法,这个后面会考虑。

对于这里的具体问题,事实上是cache功能。可以推广到任意有返回值的函数调用,字段取值操作是前者的子集。使用全局缓存表看起来是一个正确的选择,一个ConditionalWeakTable的临时平替可以实现为:

  • Key使用一个包含(MemberInfo,实参列表)的元组表示,Value是一个可空缓存值;
  • 对于键中的实参,如果是托管类型,需要用弱引用;
  • 数据结构上可以采用Bucket形式,访问子列表时,在可控范围内进行垃圾键删除;
  • 实参列表中任意一个弱引用为空时,则应视为垃圾键。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants