使用动态(或通过其他方式)从泛型方法调用 3rd 方程序集的重载方法?

Call 3rd-party assembly's overloaded method from generic method using dynamic (or by other means)?

更新:原来我完全错过了一些细节,直到我查看了我正在使用的库的源代码。为糟糕的示例代码道歉,试图专注于我认为相关的内容。

使用 FlatFiles NuGet 库,它有 25 个 Property(...) 方法重载。我正在尝试通过对传递的参数使用 dynamic 从我的泛型方法中分派正确的 Property(...) 重载,但这不起作用。这是我尝试过的:

using FlatFiles;
using FlatFiles.TypeMapping;

public class FixedWidthDataSource<FixedWidthRecordT> {
    public IFixedLengthTypeMapper<FixedWidthRecordT> Mapper
        = FixedLengthTypeMapper.Define<FixedWidthRecordT>()
    ;
    ...
    public void MapProperty<T>(
        Expression<Func<FixedWidthRecordT, T>> col
        , int width
        , string inputFormat = null
    ) {
        var window = new Window(width);
        Mapper.Property((dynamic)col, window);
    }
}

public class FixedWidthRecord
{
    public string First { get; set; }
    public string Last { get; set; }
}

//later
var fwds = new FixedWidthDataSource<FixedWidthRecord>();
fwds.MapProperty(c=>c.First, 5);

一些 属性 重载:

Property(Expression<Func<FixedWidthRecordT, bool>> property, Window window);
Property(Expression<Func<FixedWidthRecordT, int>> property, Window window);
Property(Expression<Func<FixedWidthRecordT, string>> property, Window window);

我得到的错误是 'FlatFiles.TypeMapping.IFixedLengthTypeMapper<FixedWidthRecord>' does not contain a definition for 'Property'

查看源代码我发现有一个 internal sealed class FixedLengthTypeMapper<TEntity> 这是从对 FixedLengthTypeMapper.Define<FixedWidthRecordT>() 的调用返回并分配给 Mapper 的对象类型。但是,IFixedLengthTypeMapper 没有 Property(...) 的任何定义,只有 FixedLengthTypeMapper 有。

希望这一切都是相关的。

也许你的情况与此有关? RuntimeBinderException – “does not contain a definition for”.

那篇文章在匿名对象的情况下得到了那个例外,但你的情况似乎相似。您的程序集正试图通过 dynamic 访问它通常看不到的东西:在您的情况下是 internal class,在他们的情况下是匿名类型。

在库中添加 [assembly: InternalsVisibleTo("Your.Assembly")] 属性听起来不是一个好的选择,但如果您可以从源代码构建它可能会暂时有所帮助。或者也许有了这些信息,您可以创建可靠的复制品。

这是我最终使它工作的方法,尽管它是通过使用库的使用文档中未描述的接口。我仍然很好奇如何解决这个问题(例如,如果我在解决方案中使用的 IFixedLengthTypeConfiguration 接口也被定义为内部接口)。

using FlatFiles;
using FlatFiles.TypeMapping;

public class FixedWidthDataSource<FixedWidthRecordT> {
    public IFixedLengthTypeConfiguration<FixedWidthRecordT> Configuration
        = FixedLengthTypeMapper.Define<FixedWidthRecordT>()
    ;
    public IFixedLengthTypeMapper<FixedWidthRecordT> Mapper;
    public FixedWidthDataSource() {
        Mapper = (IFixedLengthTypeMapper<FixedWidthRecordT>)Configuration;
    }
    ...
    public void MapProperty<T>(
        Expression<Func<FixedWidthRecordT, T>> col
        , int width
        , string inputFormat = null
    ) {
        var window = new Window(width);
        Configuration.Property((dynamic)col, window);
    }
}

public class FixedWidthRecord
{
    public string First { get; set; }
    public string Last { get; set; }
}

//later
var fwds = new FixedWidthDataSource<FixedWidthRecord>();
fwds.MapProperty(c=>c.First, 5);