Autofac PropertiesAutowired - 是否可以忽略一个或多个属性?

2023-12-21

尽管建议通过构造函数传递依赖项,但我发现使用无参数构造函数然后自动装配所有属性的开发成本显着减少,并使应用程序更易于开发和维护。然而有时(例如在视图模型上)我有一个在容器中注册的属性,但我不想在构造时填充该属性(例如绑定到容器的所选项目)。

有没有办法告诉容器在自动装配其余属性时忽略某些属性?

目前,我只是重置在激活事件中标有属性的属性:

public static IRegistrationBuilder<TLimit, ScanningActivatorData, TRegistrationStyle> 
    PropertiesAutowiredExtended<TLimit, TRegistrationStyle>(
    this IRegistrationBuilder<TLimit, ScanningActivatorData, TRegistrationStyle> builder)
{
    builder.ActivatorData.ConfigurationActions.Add(
        (type, innerBuilder) =>
        {
            var parameter = Expression.Parameter(typeof(object));
            var cast = Expression.Convert(parameter, type);
            var assignments = type.GetProperties()
                .Where(candidate => candidate.HasAttribute<NotAutowiredAttribute>())
                .Select(property => new { Property = property, Expression = Expression.Property(cast, property) })
                .Select(data => Expression.Assign(data.Expression, Expression.Default(data.Property.PropertyType)))
                .Cast<Expression>()
                .ToArray();

            if (assignments.Any())
            {
                var @action = Expression
                    .Lambda<Action<object>>(Expression.Block(assignments), parameter)
                    .Compile();

                innerBuilder.OnActivated(e =>
                {
                    e.Context.InjectUnsetProperties(e.Instance);
                    @action(e.Instance);
                });
            }
            else
            {
                innerBuilder.OnActivated(e => e.Context.InjectUnsetProperties(e.Instance));
            }
        });

    return builder;
}

有一个更好的方法吗?


不确定这是一个更好的方法,但您可以从另一侧出发,通过 WithProperty 语法仅注册所需的属性。优点是 Autofac 不会解决不必要的服务。这是一个工作示例:

public class MyClass
{
    public MyDependency MyDependency { get; set; }
    public MyDependency MyExcludeDependency { get; set; }
}
public class MyDependency {}

public class Program
{
    public static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<MyDependency>();
        builder.RegisterType<MyClass>().WithPropertiesAutowiredExcept("MyExcludeDependency");

        using (var container = builder.Build())
        {
            var myClass = container.Resolve<MyClass>();

            Console.WriteLine(myClass.MyDependency == null);
            Console.WriteLine(myClass.MyExcludeDependency == null);
        }
    }
}

public static class PropertiesAutowiredExtensions
{
    // Extension that registers only needed properties
    // Filters by property name for simplicity
    public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TRegistrationStyle>
        WithPropertiesAutowiredExcept<TLimit, TReflectionActivatorData, TRegistrationStyle>(
        this IRegistrationBuilder<TLimit, TReflectionActivatorData, TRegistrationStyle> registrationBuilder,
        params string[] propertiesNames)
        where TReflectionActivatorData : ReflectionActivatorData
    {
        var type = ((IServiceWithType)registrationBuilder.RegistrationData.Services.Single()).ServiceType;

        foreach (var property in type
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(pi => pi.CanWrite && !propertiesNames.Contains(pi.Name)))
        {
            // There's no additional checks like in PropertiesAutowired for simplicity
            // You can add them from Autofac.Core.Activators.Reflection.AutowiringPropertyInjector.InjectProperties

            var localProperty = property;
            registrationBuilder.WithProperty(
                new ResolvedParameter(
                    (pi, c) =>
                        {
                            PropertyInfo prop;
                            return pi.TryGetDeclaringProperty(out prop) &&
                                   prop.Name == localProperty.Name;
                        },
                    (pi, c) => c.Resolve(localProperty.PropertyType)));
        }

        return registrationBuilder;
    }

    // From Autofac.Util.ReflectionExtensions
    public static bool TryGetDeclaringProperty(this ParameterInfo pi, out PropertyInfo prop)
    {
        var mi = pi.Member as MethodInfo;
        if (mi != null && mi.IsSpecialName && mi.Name.StartsWith("set_", StringComparison.Ordinal)
            && mi.DeclaringType != null)
        {
            prop = mi.DeclaringType.GetProperty(mi.Name.Substring(4));
            return true;
        }

        prop = null;
        return false;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Autofac PropertiesAutowired - 是否可以忽略一个或多个属性? 的相关文章

随机推荐

  • JWT 令牌 SSO 流程

    我有一个关于 JWT 的 SSO 流程的简单问题 假设我们有单独的授权服务器 它向客户端应用程序 服务器和资源服务器提供 JWT 客户端尝试使用该令牌进行访问 问题是 资源服务器应该自行验证令牌 例如与身份验证服务器共享私有证书 还是应该请
  • Delphi 程序被 ClamAV 检测为误报

    我的 Delphi XE2 程序是always检测到含有病毒Jotti http virusscan jotti org en由 ClamAV 提供 而其他病毒扫描程序未检测到任何内容 AFAIK ClamAV通常与邮件服务器一起使用 那么
  • CefSharp WpfControl 和渲染到图像

    我们想要在 wpf 应用程序中的基于 chromium 的浏览器中显示网页 在浏览器中显示的网站也应该显示在另一个屏幕上 但没有交互 我想将 cefsharp wpf 浏览器控件和 cefsharp 离屏渲染结合起来 我可以使用一个 chr
  • 为什么 time.clock() 在 Windows Server 2008 X64 上返回如此大的值

    我在不同的机器上运行以下脚本并得到了完全不同的结果 经过的 time clock 太大了 Script import time start clock time clock time sleep 60 end clock time cloc
  • MacO 上的 PyOpenGL OpenGL 版本

    有人告诉我将旧配置文件从其他 stackoverflow 帖子切换到核心配置文件 但我似乎找不到方法来做到这一点 因此 我发布了一个更新的错误帖子来帮助我找到一种方法 CODE import glfw numpy from OpenGL G
  • 如何将 YYYYMMDDHHMMSS 转换为“date”可读的日期

    我有一组 YYYYMMDDHHMMSS 格式的日期 时间字符串 我想将其转换为可读的内容date公用事业 通常 我可以这样做 date d 2010 10 01 12 34 56 然而 date不喜欢 YYYYMMDDHHMMSS date
  • Python 相当于 Matlab 的clear、close all、clc

    在Matlab中 在每个文件的开头 我通常写 clear close all clc Python中有类似的东西吗 大多数人在测试脚本时会做什么 这里的问题是 plt show 是阻塞的 并且在手动关闭窗口之前不会返回到脚本 您可以尝试 p
  • 类型错误:__init_subclass__() 不接受关键字参数

    我正在尝试创建一个元类 但是当我将其分配给另一个类时 我收到错误 类型错误 init subclass 不接受关键字参数 但我没有实施任何 init subclass 为什么要调用这个函数 class Meta type def new c
  • 回形针 - 保存文件后运行方法?

    我正在开发一个需要接受文件上传的项目 文件上传后 我正在进行一些处理 从文件中提取信息 我最终计划在后台工作程序中运行它 但它目前正在内联运行 我尝试使用 after create 和 after save 来处理文件 但似乎我的方法是在
  • 如何在 MATLAB 编辑器中启用自动单词完成功能?

    我可以通过按 Tab 在 MATLAB 命令提示符下使用自动单词完成功能 但在使用 m 文件的编辑器时无法执行此操作 有什么方法可以在编辑器中使用制表符补全吗 根据这篇 MathWorks 博客文章 http blogs mathworks
  • LinkedIn 分享按钮 - 无法识别 og:image

    我正在尝试与 og 标签共享页面 其中一个标签是 og image 如以下链接所述 https developer linkedin com documents setting display tags shares https devel
  • 在 vim 中打开与当前文件相同的文件夹中的文件

    在vim中 当我打开一个缓冲区时 我经常需要加载该文件所在目录中的另一个文件 但因为我通常不这样做cd进入其中 将pwd是父文件夹 所以我每次都必须重新输入路径 这有捷径吗 或者将密码更改为文件所在目录的方法 example cd src
  • 如何确定一个 3D 对象是否适合另一个 3D 对象(容器)?

    给定两个 3D 对象 我如何找到一个是否适合第二个对象 并找到该对象在容器中的位置 应平移和旋转对象以适合容器 但不得进行其他修改 其他并发症 相同的情况 但寻找最适合的解决方案 即使它不是正确的匹配 最小化不适合容器的物体的体积 支持弹性
  • Puppeteer:如何监听对象事件

    是否可以监听页内对象调度的事件 假设我访问的页面中有以下代码 var event new CustomEvent status detail ok window addEventListener status function e cons
  • 强制 git push + pull 超时

    我发现的所有问题都想避免 git 推 拉超时 就我而言 我想强迫他们 我的推 拉都是通过 ssh 传输到在某个时间点可能不可用的远程计算机 例如 我有一个脚本可以推送到两个远程公共存储库 我不希望这个脚本在推送到第一个存储库并且该机器不可用
  • Flexslider 和从右到左的语言支持

    我在 WordPress 上安装了一个包含 Flexslider 的模板 我的语言是从右到左 RTL 书写的 当页面为 RTL 时 Flexslider 停止并且不显示图像 我该如何解决这个问题 Flex 滑块不支持 RTL 语言 解决这个
  • C++:崩溃时不显示 glibc 的回溯和内存映射

    我正在使用 Python 进行自动 C 代码测试 所以我有一个编译和执行 C 代码的 Python 脚本 当 C 代码崩溃时 即使我重定向 libc 输出也可以从我的 Python 脚本输出中看到cout and cerr正在执行的 C 程
  • 从数据库更新模型时出现实体框架错误,反之亦然

    当我尝试使用 VS Express 2013 for web EF6 1 1 和 NET Framework 4 5 从数据库更新模型时 会发生以下情况 在本例中 我只是在表定义中向表中添加了一个字段并更新了数据库 之后 我在 EDMX 模
  • 使用GridSearchCV时出现值错误

    我正在使用 GridSearchCV 进行分类 我的代码是 parameter grid SVM dual True False loss squared hinge hinge penalty l1 l2 clf GridSearchCV
  • Autofac PropertiesAutowired - 是否可以忽略一个或多个属性?

    尽管建议通过构造函数传递依赖项 但我发现使用无参数构造函数然后自动装配所有属性的开发成本显着减少 并使应用程序更易于开发和维护 然而有时 例如在视图模型上 我有一个在容器中注册的属性 但我不想在构造时填充该属性 例如绑定到容器的所选项目 有