【问题标题】:F# Unity Design-Time ConfigurationF# Unity 设计时配置
【发布时间】:2014-05-21 13:44:10
【问题描述】:

可以让它在 C# 中工作:

  • 创建名为 UnityCSharp 的 C# 控制台应用程序
  • 添加 Unity NuGet
  • 参考 System.Configuration
  • 如下添加App.config和C#代码,就可以了

C# 的 App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="myAlias" type="UnityCSharp.ILogger, UnityCSharp" />
    <container>
      <register type="myAlias" mapTo="UnityCSharp.Logger, UnityCSharp" />
      <register type="myAlias" mapTo="UnityCSharp.SpecialLogger, UnityCSharp" name="special" />
    </container>
  </unity>
</configuration>

C#:

using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace UnityCSharp
{
    public interface ILogger { string SayHello(); }
    public class Logger : ILogger { public string SayHello() { return "hello"; } }
    public class SpecialLogger : ILogger { public string SayHello() { return "special hello"; } }

    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer().LoadConfiguration();
            Console.WriteLine(container.Resolve<ILogger>().SayHello()); // --> "hello"
            Console.WriteLine(container.Resolve<ILogger>("special").SayHello()); // --> "special hello"
            Console.ReadLine();
        }
    }
}

但不能在 F# 中重复(同样是控制台应用,名为 UnityFSharp,相同的 NuGet 和 System.Configuration 引用)。

F# 的 App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="myAlias" type="UnityFSharp.ILogger, UnityFSharp" />
    <container>
      <register type="myAlias" mapTo="UnityFSharp.Logger, UnityFSharp" />
      <register type="myAlias" mapTo="UnityFSharp.SpecialLogger, UnityFSharp" name="special" />
    </container>
  </unity>
</configuration>

F#:

open System;
open Microsoft.Practices.Unity
open Microsoft.Practices.Unity.Configuration

type ILogger = abstract SayHello : unit -> string
type Logger() = interface ILogger with member x.SayHello () = "hello"
type SpecialLogger() = interface ILogger with member x.SayHello () = "special hello"

[<EntryPoint>]
let main argv = 
    let container = (new UnityContainer()).LoadConfiguration() // CRASHES HERE
    Console.WriteLine (container.Resolve<ILogger>().SayHello()) // --> "hello"
    Console.WriteLine (container.Resolve<ILogger>("special").SayHello()) // --> "special hello"
    Console.ReadLine() |> ignore
    0

会失败:

无法解析类型名称或别名 myAlias。请检查 您的配置文件并验证此类型名称。

我了解 F# 中的命名方式不同(http://ilspy.net/ 截图如下)。 但是我究竟怎样才能让它工作呢? 我尝试过各种 F# 模块、命名空间和 App.config 版本。 只有一个工作示例会有所帮助! (我可以重组我的 F#)

【问题讨论】:

    标签: dependency-injection f# unity-container design-time


    【解决方案1】:

    类型在这里定义的方式,它们编译成被称为的类型

    • Program+ILogger
    • Program+Logger
    • Program+SpecialLogger

    因为它们是在 Program 模块中定义的。

    一种选择是编辑配置文件以匹配名称:

    <alias alias="myAlias" type="Program+ILogger, UnityFSharp" />
    <container>
      <register type="myAlias" mapTo="Program+Logger, UnityFSharp" />
      <register type="myAlias" mapTo="Program+SpecialLogger, UnityFSharp" name="special" />
    </container>
    

    我想到的方法是在程序崩溃之前向程序添加一行:

    Console.WriteLine typeof<ILogger>
    

    如果您不喜欢这些模块名称,可以将类型放在适当的命名空间中:

    namespace Ploeh.Samples
    
    type ILogger = abstract SayHello : unit -> string
    type Logger() = interface ILogger with member x.SayHello () = "hello"
    type SpecialLogger() = interface ILogger with member x.SayHello () = "special hello"
    

    但是,这需要将它们放在一个单独的文件中,因为 main 函数是在 Program 模块中定义的。有了上面的命名空间,名字就变成了:

    • Ploeh.Samples.ILogger
    • Ploeh.Samples.Logger
    • Ploeh.Samples.SpecialLogger

    【讨论】:

    • 谢谢你,马克!您描述的两种方式都很好用! “WriteLine typeof”是一个聪明的做法。 (您第一次复制和粘贴中的小错字:Program+ILogger --> Program+Logger 在第二次)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2010-12-28
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多