如何使用调用相同方法的2个不同对象来定义类

时间:2016-03-25 22:04:51

标签: c# interface

我有一个使用ftp和sftp调用的项目(使用System.Net.FtpClient和Renci.SshNet)。我想在两种情况下都有标准调用,即使用相同的参数调用Connect函数和Upload函数。我觉得我必须使用一个界面,但我是绿色的接口,我卡住了。我在这里需要一些指示。到目前为止我实现了2个功能进行测试,但它不优雅,必须有其他方法。例如,我将一个对象作为GetWorkingDirectory中的参数传递,但这感觉不对,我无法正确看到如何做到这一点。

这是我的界面:

interface IRemoteCopy
{
    object Connect(string Host, int Port, string Username, string Password, string Fingerprint);
    string GetWorkingDirectory(object objRemote, string Directory);
}

以下是我的课程:

public class FTPCopy : IRemoteCopy
{
    public object Connect(string Host, int Port, string Username, string Password, string Fingerprint)
    {
        int ftpPort = 21;      // default ftp port

        if (Port == 0)
            ftpPort = Port;

        FtpClient ftp = new FtpClient();

        ftp.Host = Host;
        ftp.Port = ftpPort;
        ftp.Credentials = new NetworkCredential(Username, Password);

        return ftp;
    }

    public string GetWorkingDirectory(object objftp, string Directory)
    {
        FtpClient ftp = (FtpClient)objftp;

        ftp.SetWorkingDirectory(Directory);

        return ftp.GetWorkingDirectory();
    }
}

public class SFTPCopy : IRemoteCopy
{
    public object Connect(string Host, int Port, string Username, string Password, string Fingerprint)
    {
        int sftpPort = 22;      // default sftp port

        if (Port == 0)
            sftpPort = Port;

        ConnectionInfo connInfo = new ConnectionInfo(Host, sftpPort, Username, new AuthenticationMethod[]{
                new PasswordAuthenticationMethod(Username, Password)
            });

        SftpClient sftp = new SftpClient(connInfo);
        sftp.HostKeyReceived += delegate(object sender, HostKeyEventArgs e)
        {
            if (Fingerprint.ToLower() == (e.HostKeyName + " " + e.KeyLength + " " + BitConverter.ToString(e.FingerPrint).Replace("-", ":")).ToLower())
                e.CanTrust = true;
            else
                e.CanTrust = false;
        };

        sftp.Connect();

        return sftp;
    }

    public string GetWorkingDirectory(object objftp, string Directory)
    {
        return Directory;
    }
}

任何人都可以在这里指导我吗?

2 个答案:

答案 0 :(得分:1)

有几种方法可以解决这个问题。我建议你写一个ftp客户端实现的接口IWorkingDirectory,它有一个方法

GetWorkingDirectory(string dir). 

IRemoteCopy的Connect方法的界面将成为:

IWorkingDirectory Connect(string Host, int Port, string Username, string Password, string Fingerprint);

然后你可以简化对

的调用
public string GetWorkingDirectory(IWorkingDirectory client, string dir)
{
    return client.GetWorkingDirectory(dir);
}

根据调用方法的不同,您甚至可以考虑不在IRemoteCopy中实现此方法,因为在此之前您很可能会调用Connect,因此您可以调用简单的

var client = remoteCopy.Connect(...);
client.GetWorkingDirectory(dir);

然后,您可以有效地使IRemoteCopy成为IFtpClient的抽象工厂(因为两个客户端类可能比GetWorkingDirectory方法共享更多,我建议创建一个提供所有共享功能的接口)。

我建议您查看本网站有关开放/封闭原则的信息: http://joelabrahamsson.com/a-simple-example-of-the-openclosed-principle/

编辑: 我刚刚意识到,客户端类在不同的程序集中,因此不在您的代码中。在这种情况下,最好将IRemoteCopy方法签名更改为不接收客户端作为参数。您可以在具有相应客户端的具体类中拥有一个私有字段,因为显然它们每个类总是相同的。 然后,您可以在Connect调用上设置这些字段,或直接在类实例化中设置这些字段。我更喜欢后者,因为对于IRemoteCopy的用户来说它似乎不太容易出错。

另一种可能性是将这些客户端打包成您自己的包装器(通过构建适配器 - https://en.wikipedia.org/wiki/Adapter_pattern - 或者如果基本客户端没有通过从它们继承来密封),那么您可以使用接口库我之前提出的方法。

答案 1 :(得分:0)

在探索泛型,重载方法和接口之后,我想出了这个解决方案。如果您认为有更好的事情,请告诉我们:

IDirectory.cs:

using System;
using System.Text;

namespace ReleaseManager.Interfaces
{
    interface IDirectory
    {
        void Connect(string Host, int Port, string Username, string Password, string Fingerprint);
        string GetWorkingDirectory(string Directory);
        void ListDirectory(string Directory);
        void CreateDirectory(string Directory);
        void DeleteDirectory(string Directory);
        Boolean DirectoryExists(string Directory);
        void WriteAllText(string FileName, string Content, Encoding enc);
        void CopyFile(string srcFile, string dstFile);
        void Disconnect();
    }

}

Directory.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ReleaseManager.BusinessObjects
{
    public class RemoteDirInfo
    {
        public string Name { get; set; }
        public string ModifiedDate { get; set; }
    }

    public class RemoteFileInfo
    {
        public string Name { get; set; }
        public string ModifiedDate { get; set; }
        public long Size { get; set; }
    }

    public class RemoteInfo
    {
        public string Error { get; set; }
        public string CurrentDirectory { get; set; }
        public List<RemoteDirInfo> DirInfo { get; set; }
        public List<RemoteFileInfo> FileInfo { get; set; }
    }

}

FTPDirectory.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using System.Net.FtpClient;
using System.Net;
using System.Text;
using System.IO;


namespace ReleaseManager.BusinessObjects
{
    public class FTPDirectory : IDirectory
    {
        private FtpClient client;
        public RemoteInfo Info;

        public FTPDirectory()
        {
            this.client = new FtpClient();

            this.Info = new RemoteInfo();
            this.Info.DirInfo = new List<RemoteDirInfo>();
            this.Info.FileInfo = new List<RemoteFileInfo>();
            this.Info.Error = "";
        }

        public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
        {
            int ftpPort = 21;      // default ftp port

            if (Port != 0)
                ftpPort = Port;

            this.client.Host = Host;
            this.client.Port = ftpPort;
            this.client.Credentials = new NetworkCredential(Username, Password);
        }

        public string GetWorkingDirectory(string Directory)
        {
            this.client.SetWorkingDirectory(Directory);

            return this.client.GetWorkingDirectory();
        }

        public void ListDirectory(string Directory)
        {
            this.client.SetWorkingDirectory(Directory);

            foreach (var item in this.client.GetListing(this.client.GetWorkingDirectory()))
            {
                switch (item.Type)
                {
                    case FtpFileSystemObjectType.Directory:
                        if (item.Name != "." && item.Name != "..")
                            this.Info.DirInfo.Add(new RemoteDirInfo
                            {
                                Name = item.Name,
                                ModifiedDate = item.Modified.ToString("yyyy/MM/dd HH:mm:ss")
                            });

                        break;

                    case FtpFileSystemObjectType.File:
                        this.Info.FileInfo.Add(new RemoteFileInfo
                        {
                            Name = item.Name,
                            ModifiedDate = item.Modified.ToString("yyyy/MM/dd HH:mm:ss"),
                            Size = item.Size
                        });

                        break;
                }
            }
        }

        public void CreateDirectory(string Directory)
        {
            this.client.CreateDirectory(Directory);
        }

        public void DeleteDirectory(string Directory)
        {
            this.client.DeleteDirectory(Directory, true, FtpListOption.Recursive);
        }

        public void CopyFile(string srcFile, string dstFile)
        {
            using (var fileStream = System.IO.File.OpenRead(srcFile))
            using (var ftpStream = this.client.OpenWrite(dstFile.Replace("\\", "/")))
            {
                var buffer = new byte[8 * 1024];
                int count;

                while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ftpStream.Write(buffer, 0, count);
                }
            }
        }

        public void WriteAllText(string Filename, string Content, Encoding enc = null)
        {
            byte[] byteArray;

            if (enc == null)
                byteArray = Encoding.ASCII.GetBytes(Content);
            else
                byteArray = enc.GetBytes(Content);

            using (MemoryStream stream = new MemoryStream(byteArray))
            using (var ftpStream = this.client.OpenWrite(Filename.Replace("\\", "/")))
            {
                var buffer = new byte[8 * 1024];
                int count;

                while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ftpStream.Write(buffer, 0, count);
                }
            }
        }

        public Boolean DirectoryExists(string Directory)
        {
            return this.client.DirectoryExists(Directory);
        }

        public void Disconnect()
        {
            this.client.Disconnect();
        }
    }

}

SFTPDirectory.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;
using System.Text;
using System.IO;

namespace ReleaseManager.BusinessObjects
{
    public class SFTPDirectory : IDirectory
    {
        public SftpClient client;
        public RemoteInfo Info;

        public SFTPDirectory()
        {
            this.Info = new RemoteInfo();
            this.Info.DirInfo = new List<RemoteDirInfo>();
            this.Info.FileInfo = new List<RemoteFileInfo>();
            this.Info.Error = "";
        }

        public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
        {
            int sftpPort = 22;      // default sftp port

            if (Port != 0)
                sftpPort = Port;

            ConnectionInfo connInfo = new ConnectionInfo(Host, sftpPort, Username, new AuthenticationMethod[]{
                    new PasswordAuthenticationMethod(Username, Password)
                });

            this.client = new SftpClient(connInfo);
            this.client.HostKeyReceived += delegate(object sender, HostKeyEventArgs e)
            {
                if (Fingerprint.ToLower() == (e.HostKeyName + " " + e.KeyLength + " " + BitConverter.ToString(e.FingerPrint).Replace("-", ":")).ToLower())
                    e.CanTrust = true;
                else
                    e.CanTrust = false;
            };

            this.client.Connect();
        }

        public string GetWorkingDirectory(string Directory)
        {
            return Directory;
        }

        public void ListDirectory(string Directory)
        {
            List<SftpFile> files = this.client.ListDirectory(Directory).ToList();

            foreach (var file in files)
            {
                if (file.IsDirectory)
                {
                    if (file.Name != "." && file.Name != "..")
                        this.Info.DirInfo.Add(new RemoteDirInfo
                        {
                            Name = file.Name,
                            ModifiedDate = file.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss")
                        });
                }
                else
                {
                    this.Info.FileInfo.Add(new RemoteFileInfo
                    {
                        Name = file.Name,
                        ModifiedDate = file.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"),
                        Size = file.Length
                    });
                }
            }
        }

        public void CreateDirectory(string Directory)
        {
            this.client.CreateDirectory(Directory);
        }

        public void DeleteDirectory(string Directory)
        {
            this.client.DeleteDirectory(Directory);
        }

        public void CopyFile(string srcFile, string dstFile)
        {
            using (var uplfileStream = System.IO.File.OpenRead(srcFile))
            {
                this.client.UploadFile(uplfileStream, dstFile.Replace("\\", "/"), true);
            }
        }

        public void WriteAllText(string Filename, string Content, Encoding enc = null)
        {
            byte[] byteArray;

            if (enc == null)
                byteArray = Encoding.ASCII.GetBytes(Content);
            else
                byteArray = enc.GetBytes(Content);

            using (MemoryStream stream = new MemoryStream(byteArray))
            {
                this.client.UploadFile(stream, Filename.Replace("\\", "/"), true);
            }
        }

        public Boolean DirectoryExists(string Directory)
        {
            return this.client.Exists(Directory);
        }

        public void Disconnect()
        {
            this.client.Disconnect();
        }
    }
}

LocalDirectory.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using System.Net;
using System.Text;
using System.IO;


namespace ReleaseManager.BusinessObjects
{
    public class LocalDirectory : IDirectory
    {
        public RemoteInfo Info;

        public LocalDirectory()
        {
            this.Info = new RemoteInfo();
            this.Info.DirInfo = new List<RemoteDirInfo>();
            this.Info.FileInfo = new List<RemoteFileInfo>();
            this.Info.Error = "";
        }

        public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
        {
        }

        public string GetWorkingDirectory(string Directory)
        {
            return Directory;
        }

        public void ListDirectory(string Directory)
        {
            DirectoryInfo di = new DirectoryInfo(Directory);

            foreach (var item in di.EnumerateDirectories("*"))
            {
                if (item.Name != "." && item.Name != "..")
                    this.Info.DirInfo.Add(new RemoteDirInfo
                    {
                        Name = item.Name,
                        ModifiedDate = item.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss")
                    });
            }

            foreach (var item in di.EnumerateFiles("*"))
            {
                this.Info.FileInfo.Add(new RemoteFileInfo
                {
                    Name = item.Name,
                    ModifiedDate = item.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"),
                    Size = item.Length
                });
            }
        }

        public void CreateDirectory(string Directory)
        {
            System.IO.Directory.CreateDirectory(Directory);
        }

        public void DeleteDirectory(string Directory)
        {
            System.IO.Directory.Delete(Directory, true);
        }

        public void CopyFile(string srcFile, string dstFile)
        {
            System.IO.File.Copy(srcFile, dstFile);
        }

        public void WriteAllText(string Filename, string Content, Encoding enc = null)
        {
            if (enc == null)
                System.IO.File.WriteAllText(Filename, Content);
            else
                System.IO.File.WriteAllText(Filename, Content, enc);
        }

        public Boolean DirectoryExists(string Directory)
        {
            return System.IO.Directory.Exists(Directory);
        }

        public void Disconnect()
        {
        }
    }

}

RemoteBrowse方法的实现:

public JsonResult RemoteBrowse(string Protocol, string Host, int Port, string Username, string Password, string Directory, string Fingerprint = "")
{
    dynamic Connector = null;

    MyMember.Init(User.Identity.Name);

    if (MyMember.ID_Member > 0)
    {
        if (Protocol == "ftp")
            Connector = new FTPDirectory();
        else if (Protocol == "sftp")
            Connector = new SFTPDirectory();
        else if (Protocol == "local")
            Connector = new LocalDirectory();

        if (Connector != null)
        {
            try
            {
                Connector.Connect(Host, Port, Username, Password, Fingerprint);

                while (true)
                {
                    Boolean Mod = false;

                    if (Directory.Length >= 2)
                    {
                        if (Directory.Substring(0, 2) == "//")
                        {
                            Directory = Directory.Substring(1);
                            Mod = true;
                        }
                        else if (Directory.Substring(0, 2) == "..")
                        {
                            Directory = Directory.Substring(2);
                            Mod = true;
                        }
                    }
                    else if (Directory.Length >= 3)
                    {
                        if (Directory.Substring(0, 3) == "/..")
                        {
                            Directory = Directory.Substring(3);
                            Mod = true;
                        }
                    }

                    if (!Mod)
                        break;
                }

                if (Directory.Length > 1 && Directory != "/")
                {
                    if (Directory.Substring(0, 1) != "/")
                        Directory = "/" + Directory;

                    if (Directory.Substring(Directory.Length - 1) == "/")
                        Directory = Directory.Substring(0, Directory.Length - 1);

                    if (Directory.Substring(Directory.Length - 3) == "/..")     // go one directory up
                    {
                        Directory = Directory.Substring(0, Directory.Length - 3);
                        Directory = Directory.Substring(0, Directory.LastIndexOf('/'));
                    }
                }

                if (Directory == "")
                    Directory = "/";

                Connector.Info.CurrentDirectory = Connector.GetWorkingDirectory(Directory);

                Connector.ListDirectory(Directory);
                Connector.Disconnect();
            }
            catch (Exception ex)
            {
                Connector.Info.Error = ex.Message;

                if (ex.InnerException != null)
                    Connector.Info.Error += '\n' + ex.InnerException.Message;
            }
        }
    }

    return Json((Connector != null) ? Connector.Info : null, JsonRequestBehavior.AllowGet);
}