C# 将接口作为参数传递给类构造函数

C# 将接口作为参数传递给类构造函数,c#,.net,itext7,C#,.net,Itext7,我正在使用iText7读取PDF文件数据,并根据它们在PDF文件中的位置创建一个xml文件。 我的问题是 iText7程序集中有一个类LocationTextExtractionStrategy,如下所示 public class LocationTextExtractionStrategy : ITextExtractionStrategy, IEventListener { public LocationTextExtractionStrategy(ITextChunkLocatio

我正在使用iText7读取PDF文件数据,并根据它们在PDF文件中的位置创建一个xml文件。 我的问题是

iText7程序集中有一个类
LocationTextExtractionStrategy
,如下所示

public class LocationTextExtractionStrategy : ITextExtractionStrategy, IEventListener
{
    public LocationTextExtractionStrategy(ITextChunkLocationStrategy strat);
    public virtual void EventOccurred(IEventData data, EventType type);

    public interface ITextChunkLocationStrategy
    {
        ITextChunkLocation CreateLocation(TextRenderInfo renderInfo, LineSegment baseline);
    }
}
public class TextLocationExtractionStrategy : LocationTextExtractionStrategy
{
    ITextChunkLocationStrategy locationstrategy ;
    public TextLocationExtractionStrategy(ITextChunkLocationStrategy strategy)
    {
        locationstrategy = strategy;
    }

    public override void EventOccurred(IEventData data, EventType type)
    {
        if (!type.Equals(EventType.RENDER_TEXT))
            return;

        TextRenderInfo renderInfo = (TextRenderInfo)data;

        string curFont = renderInfo.GetFont().GetFontProgram().ToString();

        float curFontSize = renderInfo.GetFontSize();

        IList<TextRenderInfo> text = renderInfo.GetCharacterRenderInfos();
        foreach (TextRenderInfo t in text)
        {
            LineSegment lineSegment = t.GetBaseline();
            string letter = t.GetText();
            Vector letterStart = t.GetBaseline().GetStartPoint();
            Vector letterEnd = t.GetAscentLine().GetEndPoint();
            Rectangle letterRect = new Rectangle(letterStart.Get(0), letterStart.Get(1),
                letterEnd.Get(0) - letterStart.Get(0), letterEnd.Get(1) - letterStart.Get(1));

            if (letter != " " && !letter.Contains(' '))
            {
                ITextChunkLocation loc = locationstrategy.CreateLocation(t, lineSegment);
                UTextChunk chunk = new UTextChunk(t, t.GetText(), loc);
                t.GetText();
                t.GetBaseline().GetBoundingRectangle();

                m_locationResult.Add(chunk);
            }
        }
    }
}
现在我将这个类继承到我的项目类中,如下所示

public class LocationTextExtractionStrategy : ITextExtractionStrategy, IEventListener
{
    public LocationTextExtractionStrategy(ITextChunkLocationStrategy strat);
    public virtual void EventOccurred(IEventData data, EventType type);

    public interface ITextChunkLocationStrategy
    {
        ITextChunkLocation CreateLocation(TextRenderInfo renderInfo, LineSegment baseline);
    }
}
public class TextLocationExtractionStrategy : LocationTextExtractionStrategy
{
    ITextChunkLocationStrategy locationstrategy ;
    public TextLocationExtractionStrategy(ITextChunkLocationStrategy strategy)
    {
        locationstrategy = strategy;
    }

    public override void EventOccurred(IEventData data, EventType type)
    {
        if (!type.Equals(EventType.RENDER_TEXT))
            return;

        TextRenderInfo renderInfo = (TextRenderInfo)data;

        string curFont = renderInfo.GetFont().GetFontProgram().ToString();

        float curFontSize = renderInfo.GetFontSize();

        IList<TextRenderInfo> text = renderInfo.GetCharacterRenderInfos();
        foreach (TextRenderInfo t in text)
        {
            LineSegment lineSegment = t.GetBaseline();
            string letter = t.GetText();
            Vector letterStart = t.GetBaseline().GetStartPoint();
            Vector letterEnd = t.GetAscentLine().GetEndPoint();
            Rectangle letterRect = new Rectangle(letterStart.Get(0), letterStart.Get(1),
                letterEnd.Get(0) - letterStart.Get(0), letterEnd.Get(1) - letterStart.Get(1));

            if (letter != " " && !letter.Contains(' '))
            {
                ITextChunkLocation loc = locationstrategy.CreateLocation(t, lineSegment);
                UTextChunk chunk = new UTextChunk(t, t.GetText(), loc);
                t.GetText();
                t.GetBaseline().GetBoundingRectangle();

                m_locationResult.Add(chunk);
            }
        }
    }
}
由于我们不能创建接口的实例,我不知道如何将值传递给接口类型的参数。在上面的几行中,我只是将其赋值为null并调用构造函数,但是如果将null值赋值给它,它会说“对象引用未设置为对象的实例”

你能帮我解决这个问题吗


如果在提出我的问题时有任何问题,请告诉我或纠正我。

如果您查看基类的源代码
LocationTextExtractionStrategy
(它是开源的,所以请查看源代码!),您将看到它不仅具有带
ITextChunkLocationStrategy
参数的构造函数,它也有一个没有参数的构造函数

该构造函数实际实例化了该接口的实现,并将其转发给您引用的同一个构造函数:

public LocationTextExtractionStrategy()
    : this(new _ITextChunkLocationStrategy_85()) {
}

private sealed class _ITextChunkLocationStrategy_85 : LocationTextExtractionStrategy.ITextChunkLocationStrategy {
    public _ITextChunkLocationStrategy_85() {
    }

    public ITextChunkLocation CreateLocation(TextRenderInfo renderInfo, LineSegment baseline) {
        return new TextChunkLocationDefaultImp(baseline.GetStartPoint(), baseline.GetEndPoint(), renderInfo.GetSingleSpaceWidth());
    }
}
由于您希望使用
ITextChunkLocationStrategy
实现,而基类不为其提供getter,因此不能简单地使用没有参数的另一个构造函数。您不能实例化这个
\u ITextChunkLocationStrategy\u 85
类,因为它是私有的。您不能简单地将
\u ITextChunkLocationStrategy\u 85
复制到您的代码中,因为
TextChunkLocationDefaultImp
内部的

但是,您可以做的是将
TextChunkLocationDefaultImp
复制到您的代码中,然后将
\u ITextChunkLocationStrategy\u 85
复制到您的代码中,使用该类的副本替换基类中使用的
TextChunkLocationDefaultImp
,然后实例化
\u ITextChunkLocationStrategy\u 85
类的副本,以最终获得
ITextChunkLocationStrategy
实现实例

或者,你可以试着进行反思和内省。不过,这可能会导致维护问题

如果一个库提供了泛化某个东西的方法,然后隐藏了它的默认实现,那么这将是一个真正的麻烦


作为参考,
TextChunkLocationDefaultImp
当前的实现如下

internal class TextChunkLocationDefaultImp : ITextChunkLocation {
    private const float DIACRITICAL_MARKS_ALLOWED_VERTICAL_DEVIATION = 2;

    /// <summary>the starting location of the chunk</summary>
    private readonly Vector startLocation;

    /// <summary>the ending location of the chunk</summary>
    private readonly Vector endLocation;

    /// <summary>unit vector in the orientation of the chunk</summary>
    private readonly Vector orientationVector;

    /// <summary>the orientation as a scalar for quick sorting</summary>
    private readonly int orientationMagnitude;

    /// <summary>perpendicular distance to the orientation unit vector (i.e.</summary>
    /// <remarks>
    /// perpendicular distance to the orientation unit vector (i.e. the Y position in an unrotated coordinate system)
    /// we round to the nearest integer to handle the fuzziness of comparing floats
    /// </remarks>
    private readonly int distPerpendicular;

    /// <summary>distance of the start of the chunk parallel to the orientation unit vector (i.e.</summary>
    /// <remarks>distance of the start of the chunk parallel to the orientation unit vector (i.e. the X position in an unrotated coordinate system)
    ///     </remarks>
    private readonly float distParallelStart;

    /// <summary>distance of the end of the chunk parallel to the orientation unit vector (i.e.</summary>
    /// <remarks>distance of the end of the chunk parallel to the orientation unit vector (i.e. the X position in an unrotated coordinate system)
    ///     </remarks>
    private readonly float distParallelEnd;

    /// <summary>the width of a single space character in the font of the chunk</summary>
    private readonly float charSpaceWidth;

    public TextChunkLocationDefaultImp(Vector startLocation, Vector endLocation, float charSpaceWidth) {
        this.startLocation = startLocation;
        this.endLocation = endLocation;
        this.charSpaceWidth = charSpaceWidth;
        Vector oVector = endLocation.Subtract(startLocation);
        if (oVector.Length() == 0) {
            oVector = new Vector(1, 0, 0);
        }
        orientationVector = oVector.Normalize();
        orientationMagnitude = (int)(Math.Atan2(orientationVector.Get(Vector.I2), orientationVector.Get(Vector.I1)
            ) * 1000);
        // see http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
        // the two vectors we are crossing are in the same plane, so the result will be purely
        // in the z-axis (out of plane) direction, so we just take the I3 component of the result
        Vector origin = new Vector(0, 0, 1);
        distPerpendicular = (int)(startLocation.Subtract(origin)).Cross(orientationVector).Get(Vector.I3);
        distParallelStart = orientationVector.Dot(startLocation);
        distParallelEnd = orientationVector.Dot(endLocation);
    }

    public virtual int OrientationMagnitude() {
        return orientationMagnitude;
    }

    public virtual int DistPerpendicular() {
        return distPerpendicular;
    }

    public virtual float DistParallelStart() {
        return distParallelStart;
    }

    public virtual float DistParallelEnd() {
        return distParallelEnd;
    }

    /// <returns>the start location of the text</returns>
    public virtual Vector GetStartLocation() {
        return startLocation;
    }

    /// <returns>the end location of the text</returns>
    public virtual Vector GetEndLocation() {
        return endLocation;
    }

    /// <returns>the width of a single space character as rendered by this chunk</returns>
    public virtual float GetCharSpaceWidth() {
        return charSpaceWidth;
    }

    /// <param name="as">the location to compare to</param>
    /// <returns>true is this location is on the the same line as the other</returns>
    public virtual bool SameLine(ITextChunkLocation @as) {
        if (OrientationMagnitude() != @as.OrientationMagnitude()) {
            return false;
        }
        float distPerpendicularDiff = DistPerpendicular() - @as.DistPerpendicular();
        if (distPerpendicularDiff == 0) {
            return true;
        }
        LineSegment mySegment = new LineSegment(startLocation, endLocation);
        LineSegment otherSegment = new LineSegment(@as.GetStartLocation(), @as.GetEndLocation());
        return Math.Abs(distPerpendicularDiff) <= DIACRITICAL_MARKS_ALLOWED_VERTICAL_DEVIATION && (mySegment.GetLength
            () == 0 || otherSegment.GetLength() == 0);
    }

    /// <summary>
    /// Computes the distance between the end of 'other' and the beginning of this chunk
    /// in the direction of this chunk's orientation vector.
    /// </summary>
    /// <remarks>
    /// Computes the distance between the end of 'other' and the beginning of this chunk
    /// in the direction of this chunk's orientation vector.  Note that it's a bad idea
    /// to call this for chunks that aren't on the same line and orientation, but we don't
    /// explicitly check for that condition for performance reasons.
    /// </remarks>
    /// <param name="other"/>
    /// <returns>the number of spaces between the end of 'other' and the beginning of this chunk</returns>
    public virtual float DistanceFromEndOf(ITextChunkLocation other) {
        return DistParallelStart() - other.DistParallelEnd();
    }

    public virtual bool IsAtWordBoundary(ITextChunkLocation previous) {
        // In case a text chunk is of zero length, this probably means this is a mark character,
        // and we do not actually want to insert a space in such case
        if (startLocation.Equals(endLocation) || previous.GetEndLocation().Equals(previous.GetStartLocation())) {
            return false;
        }
        float dist = DistanceFromEndOf(previous);
        if (dist < 0) {
            dist = previous.DistanceFromEndOf(this);
            //The situation when the chunks intersect. We don't need to add space in this case
            if (dist < 0) {
                return false;
            }
        }
        return dist > GetCharSpaceWidth() / 2.0f;
    }

    internal static bool ContainsMark(ITextChunkLocation baseLocation, ITextChunkLocation markLocation) {
        return baseLocation.GetStartLocation().Get(Vector.I1) <= markLocation.GetStartLocation().Get(Vector.I1) &&
             baseLocation.GetEndLocation().Get(Vector.I1) >= markLocation.GetEndLocation().Get(Vector.I1) && Math.
            Abs(baseLocation.DistPerpendicular() - markLocation.DistPerpendicular()) <= DIACRITICAL_MARKS_ALLOWED_VERTICAL_DEVIATION;
    }
}
内部类TextChunkLocationDefaultImp:ITextChunkLocation{
私有常量浮点变音符号允许的垂直偏差=2;
///块的起始位置
私有只读向量定位;
///块的结束位置
专用只读向量结束位置;
///块方向上的单位向量
私有只读向量方向向量;
///用于快速排序的标量方向
私有只读int方向大小;
///与方向单位向量的垂直距离(即。
/// 
///与方向单位向量的垂直距离(即未旋转坐标系中的Y位置)
///我们四舍五入到最接近的整数来处理比较浮点数的模糊性
/// 
私有只读int;
///平行于方向单位向量的块起点距离(即。
///平行于方向单位向量的块起点距离(即未旋转坐标系中的X位置)
///     
私有只读浮点启动;
///平行于方向单位向量的块端距离(即。
///平行于方向单位向量的块端距离(即未旋转坐标系中的X位置)
///     
私有只读浮点数;
///块字体中单个空格字符的宽度
私有只读浮点字符空间宽度;
public TextChunkLocationDefaultImp(向量位置、向量结束位置、浮点字符空间宽度){
this.startolocation=startolocation;
this.endLocation=endLocation;
this.charSpaceWidth=charSpaceWidth;
向量向量向量=结束位置。减去(起始位置);
如果(oVector.Length()==0){
oVector=新向量(1,0,0);
}
方向向量=oVector.Normalize();
orientationmagnity=(int)(Math.Atan2(orientationVector.Get(Vector.I2),orientationVector.Get(Vector.I1)
) * 1000);
//看http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
//我们相交的两个向量在同一个平面上,因此结果将完全相同
//在z轴(平面外)方向,我们只取结果的I3分量
向量原点=新向量(0,0,1);
distvertical=(int)(起始位置。减去(原点))。交叉(方向向量)。获取(向量。I3);
distParallelStart=方向向量.Dot(位置);
distParallelEnd=方向向量.Dot(endLocation);
}
公共虚拟int方向重要性(){
返回方向大小;
}
公共虚拟整数(){
返回垂直;
}
公共虚拟浮点数开始(){
返回并启动;
}
公共虚拟浮点数(){
返回端;
}
///文本的起始位置
公共虚拟向量{
返回定位;
}
///文本的结束位置
公共虚拟向量GetEndLocation(){
返回端定位;
}
///此块渲染的单个空格字符的宽度
公共虚拟浮点GetCharSpaceWidth(){
返回字符空间宽度;
}
///指向com的位置