想要直接从对象访问类属性(字段)

时间:2018-07-28 18:51:08

标签: c#

我编写了一个类,希望用作与基于Web的API传入的数据进行交互的全局数据接口。这样,该类几乎可以接受任何基本类型的值,并且可以像该基本类型一样工作。

在幕后,我将对象的“值”存储为字符串,并且在大多数情况下,该类充当String对象的克隆,除了它可以尝试在-中模拟其他任何基类。上下文。

尽管这是所有多余的问题,但我的问题是,如何使该类型的字段能够直接与其交互而不是通过访问器进行交互?

例如:

public class PolyVar
{
   protected string _myValue;

   public PolyVar() { this._myValue = ""; }

   public PolyVar(string value) { this._myValue = value; }

   public string Value { get => this._myValue; set => this._myValue = value; }
}

然后,在项目中要执行的操作:

string temp = "";
PolyVar work = ""; // in lieu of "PolyVar work = new PolyVar();"

temp = "Some string data here. " + work; // using just "work" instead of "work.Value"

所以您可以以访问/修改的方式构造类吗? 是否可以直接通过类本身提供其属性之一(在本例中为“ _myValue”),而不需要使用访问器? (因为基类已经全部支持了?)

4 个答案:

答案 0 :(得分:4)

您必须1)创建从字符串到PolyVar的隐式转换,并2)覆盖ToString(),以便在需要时将其正确转换为简单的字符串。

public class PolyVar {
   protected string _myValue;

   public PolyVar() { this._myValue = ""; }

   public PolyVar(string value) { this._myValue = value; }

   public string Value { get { return this._myValue; } set { this._myValue = value; } }

   // Override ToString() so "" + polyVar1 is correctly converted.
   public override string ToString()
   {
    return this.Value;
   }

   // Create an implicit cast operator from string to PolyVar
   public static implicit operator PolyVar(string x)
   {
    return new PolyVar( x );
   }
}


class Ppal {
    static void Main()
    {
        PolyVar work = "data"; // in lieu of "PolyVar work = new PolyVar();"
        string temp = "Some string data here: " + work;

        System.Console.WriteLine( temp );
    }
}

希望这会有所帮助。

答案 1 :(得分:1)

修改您的PolyVar类,使其覆盖ToString()方法:

public class PolyVar
{
    protected string _myValue;

    public PolyVar() { this._myValue = ""; }

    public PolyVar(string value) { this._myValue = value; }

    public string Value { get => this._myValue; set => this._myValue = value; }

    public override string ToString()
    {
        return this.Value.ToString();
    }
}

这使您可以执行以下操作...

PolyVar work = new PolyVar();
string temp = "Some string data here. " + work.ToString();

...或如下文所述的Corak,只需忽略.ToString(),因为它会自动被调用...

string temp = "Some string data here. " + work;

正如您的解释所指出的,您正在使用PolyVar的多个对象,但实际上我没有看到一种允许您跳过使用构造函数的方法。

答案 2 :(得分:1)

您无需在此处使用string,可以使用泛型:

public class PolyVar<T>
{
    public PolyVar()
    {
    }

    public PolyVar(T value)
    {
        Value = value;
    }

    // note: no reason to explicitly declare the backing field
    public T Value { get; set; }

    // return the string representation of the current value
    public override string ToString() => Value.ToString();

    // allow any type to be implicitly a PolyVar
    public static implicit operator PolyVar<T>(T value) => new PolyVar<T>(value);
}

然后将其用作:

PolyVar<string> work = "";
string data = "Some data: " + work;

这将允许您使用任何类型,而不必从中解析并转换回字符串。

如@Corak所述,如果您事先不了解T,则可以使用工厂方法来创建PolyVar<T>

public static class PolyVarFactory
{
    public static PolyVar<T> FromValue<T>(T value) => value;
}

请注意,该类必须位于非泛型类中,这样才能在不显式传入类型的情况下调用方法。

答案 3 :(得分:1)

好吧,如果其他任何人想做这样的事情,这就是我最终得到的结果:

它基本上像一个字符串,但它也便于与所有基本数字类型直接加,乘,减和除法,数字量求值(>,<,==,<=和> =)以及无懈可击的能力通过适当命名的访问器(即“ .AsInt”,“ AsFloat”,“ AsDecimal”,“ AsULong”等)充当受支持的子类型之一。它还合并了最常见的String函数(Substring,PadLeft,PadRight)以及一些我经常使用的扩展名(“ .UCWords”和“ .Filter”)。添加更多的字符串函数显然很容易。它支持基于char的ForEach枚举,以及基于索引的字符访问/分配。子字符串也已扩展为支持负的“起始位置”值(指示“起始x从末尾开始的位置”)。我将发布它,以防此类对其他人都有用,无论它是什么,是什么,或者我如何解决此处提供的一些帮助所带来的问题。哦,尽管我来回回过头,但是无论何时尝试进行转换,我都实现了本地错误捕获。因此,对替代类型的调用会始终返回一个 值。之后,您可以检查“ .HasError”(和“ .Error”)访问器,以查看是否存在问题。显然,在所有(或什至大多数)情况下,这可能都不是处理转换错误的首选方法,但这就是我一直使用的方法。提出建议和意见。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace PolyVar
{
    class PolyVar : IEnumerator<char>
    {
        protected string _value = "";
        protected string _error = "";
        protected int _position = 0;

        #region Constructors
        public PolyVar() { }

        public PolyVar(string value) => this._value = value;

        public PolyVar(XmlDocument data) => this._value = data.OuterXml;

        public PolyVar(XmlElement data) => this._value = data.OuterXml;

        public PolyVar(bool value) => this.AsBool = value;

        public PolyVar(PolyVar data) => this._value = data._value;

        public PolyVar(object data) => this._value = data.ToString();
        #endregion

        #region Operators
        public static PolyVar operator +(PolyVar left, string right) => new PolyVar(left._value + right);
        public static PolyVar operator +(string left, PolyVar right) => new PolyVar(left + right._value);

        public static PolyVar operator +(PolyVar left, PolyVar right) => new PolyVar(left._value + right._value);

        public static bool operator ==(string left, PolyVar right) => (right == left);
        public static bool operator ==(PolyVar left, string right)
        {
            if (left is null) return (right is null) || (right.Length == 0);
            if (right is null) return false;
            return right.Equals(left._value, StringComparison.InvariantCultureIgnoreCase);
        }

        public static bool operator !=(PolyVar left, string right) => !(left == right);
        public static bool operator !=(string left, PolyVar right) => !(right == left);

        public static bool operator ==(PolyVar left, PolyVar right)
        {
            if (left is null) return (right is null) || (right._value.Length == 0);
            if (right is null) return false;
            return left == right._value;
        }

        public static bool operator !=(PolyVar left, PolyVar right) => !(left == right);

        public static bool operator ==(bool left, PolyVar right) => right == left;
        public static bool operator ==(PolyVar left, bool right)
        {
            if (left is null) return false;
            return left.AsBool == right;
        }

        public static bool operator !=(PolyVar left, bool right) => !(left == right);
        public static bool operator !=(bool left, PolyVar right) => !(right == left);

        public static bool operator ==(XmlDocument left, PolyVar right) => (right == left);
        public static bool operator ==(PolyVar left, XmlDocument right)
        {
            if (left is null) return (right is null);
            if (right is null) return false;
            return String.Equals(left._value, right.OuterXml, StringComparison.InvariantCultureIgnoreCase);
        }

        public static bool operator !=(PolyVar left, XmlDocument right) => !(left == right);
        public static bool operator !=(XmlDocument left, PolyVar right) => !(right == left);

        public static bool operator ==(XmlElement left, PolyVar right) => (right == left);
        public static bool operator ==(PolyVar left, XmlElement right)
        {
            if (left is null) return (right is null);
            if (right is null) return false;
            return String.Equals(left._value, right.OuterXml, StringComparison.InvariantCultureIgnoreCase);
        }

        public static bool operator !=(PolyVar left, XmlElement right) => !(left == right);
        public static bool operator !=(XmlElement left, PolyVar right) => !(right == left);
        #endregion

        #region Accessors
        public string Value { get => this._value; set => this._value = value; }

        public int Length
        {
            get => _value.Length;
            set { if (value < _value.Length) this._value = this._value.Substring(0, value); }
        }

        public string[] Words => ((this._value.Trim().IndexOf(' ') > 0) ? this._value.Trim().Split(new string[] { " ", "\r", "\n", "\t" }, StringSplitOptions.RemoveEmptyEntries) : new string[] { this._value.Trim() });

        protected string FirstWord => this.Words[0];

        public char this[int index]
        {
            get
            {
                if ((index < 0) || (index >= _value.Length))
                    throw new ArgumentOutOfRangeException();

                return this._value[index];
            }
            set
            {
                if ((index < 0) || (index >= _value.Length))
                    throw new ArgumentOutOfRangeException();

                string work = this._value.Substring(0, index) + value;
                if (index < _value.Length - 1)
                    work += this._value.Substring(index + 1);

                this._value = work;
            }
        }

        public bool HasError => (this._error.Length > 0);
        public string Error { get { string e = this._error; this._error = ""; return e; } }

        protected bool AsBool
        {
            get
            {
                if ((this._value.Length == 0) || (this._value == string.Empty) || (this._value == null)) return false;
                return (this._value.ToLowerInvariant()[0] == 'y') ||
                       (this._value.ToLowerInvariant()[0] == 't') ||
                       ((int)this != 0);
            }

            set => this._value = (value ? "true" : "false");
        }

        public XmlDocument AsXmlDocument
        {
            set => this._value = value.OuterXml;
            get
            {
                XmlDocument doc = new XmlDocument();
                this._error = "";
                try { doc.LoadXml(this._value); }
                catch (Exception e) { this._error = e.Message; }
                return doc;
            }
        }

        public XmlElement AsXmlElement
        {
            set => this._value = value.OuterXml;
            get
            {
                XmlDocument doc = new XmlDocument();
                this._error = "";
                XmlElement result = null;
                try
                {
                    doc.LoadXml(AsXmlDocument.CreateXmlDeclaration("1.1", "UTF-8", "yes").ToString() + this._value);
                    result = (XmlElement)doc.FirstChild;
                }
                catch (Exception e)
                {
                    this._error = e.Message;
                    result = doc.CreateElement("error");
                    result.InnerText = e.Message;
                }
                return result;
            }
        }

        protected object Set { set => this._value = value.ToString(); }

        char IEnumerator<char>.Current => this._value[this._position];

        object IEnumerator.Current => this._value[this._position];
        #endregion

        #region Methods
        // Generic number conversion function: Attempts to convert the internal _myValue
        // string into the numeric type specified by the "T" designator:
        protected T ConvertToNbr<T>()
        {
            try { return (T)Convert.ChangeType(this._value, typeof(T)); }
            catch (Exception e)
            {
                this._error = e.Message;
                return default(T);
            }
        }

        public string Substring(int start, int length) =>
            (start >= 0) ? this._value.Substring(start, length) : this._value.Substring(_value.Length + start, length);

        public string Substring(int start) =>
            (start >= 0) ? this._value.Substring(start) : this._value.Substring(_value.Length + start);

        public string PadLeft(int toWidth, char with) => this._value.PadLeft(toWidth, with);

        public string PadLeft(int toWidth) => this._value.PadLeft(toWidth);

        public string PadRight(int toWidth, char with) => this._value.PadRight(toWidth, with);

        public string PadRight(int toWidth) => this._value.PadRight(toWidth);

        public char[] ToCharArray() => this._value.ToCharArray();

        public char[] ToCharArray(int startIndex, int Length) => this._value.ToCharArray(startIndex, Length);

        /// <summary>Removes all instances of a specified character from the string.</summary>
        /// <param name="value">A Char value to remove all instances of from this string.</param>
        /// <returns>The current string with all of the specified characters removed.</returns>
        public string Remove(char value) => this._value.Replace(value.ToString(), "");

        /// <summary>Removes all instances of a specified string from the string.</summary>
        /// <param name="value">A string value to remove all instances of from this string.</param>
        /// <returns>The current string with all of the specified string removed.</returns>
        public string Remove(string value) => this._value.Replace(value, "");

        /// <summary>Removes all instances of each element in a specified character array from the string.</summary>
        /// <param name="value">An array of Char value to remove all instances of from this string.</param>
        /// <returns>The current string with all of the specified characters removed.</returns>
        public string Remove(char[] values)
        {
            string result = this._value;
            foreach (char c in values) result = result.Remove(c);
            return result;
        }

        /// <summary>Extends the string class to add a UCWords function.</summary>
        /// <returns>A string with the initial letter of all words in it capitalised with any existing capitalized letters left as found.</returns>
        public string UCWords()
        {
            System.Globalization.TextInfo ti = System.Globalization.CultureInfo.InvariantCulture.TextInfo;
            return ti.ToTitleCase(this._value.ToLowerInvariant());
        }

        /// <summary>Extends the string class to add a UCWords function.</summary>
        /// <param name="strict">If set to true, all letters in the string are converted to lowercase, then the words are capitalised.</param>
        /// <returns>A string with all individual words in it capitalised.</returns>
        public string UCWords(bool strict)
        {
            if (strict) return this._value.UCWords();

            PolyVar result = new PolyVar(this._value);
            if (!(result is null) && (result.Length > 0))
                for (int i = 0; i < result.Length; i++)
                    if (((i == 0) || ("> .\t\r\n".IndexOf(result[i - 1]) > 0)) && (">abcdefghijklmnopqrstuvwxyz".IndexOf(result[i]) > 0))
                        result[i] = char.ToUpperInvariant(result[i]);

            return result;
        }

        /// <summary>Given a string of valid characters, filters all non-matching characters out of a string.</summary>
        /// <param name="validChars">A string of valid (permitted) characters to retain.</param>
        /// <param name="ignoreCase">Specifies whether case should be ignored.</param>
        /// <returns>A string containing only the permitted characters.</returns>
        public string Filter(string validChars, bool ignoreCase)
        {
            string result = this._value;
            if ((result.Length == 0) || (validChars.Length == 0)) return "";
            if (ignoreCase)
            {
                validChars = validChars.ToLowerInvariant();
                foreach (char c in validChars)
                    if (" abcdefghijklmnopqrstuvwxyz".IndexOf(c) > 0) validChars += (char)(c & 223);
            }

            int i = 0;
            while (i < result.Length)
                if (validChars.IndexOf(result.Substring(i, 1)) < 0)
                    result = result.Remove(result.Substring(i, 1));
                else i++;

            return result;
        }

        /// <summary>Given a string of valid characters, filters all non-matching (case-insensitive) characters out of a string.</summary>
        /// <param name="validChars">A string of valid (permitted) characters to retain.</param>
        /// <returns>A string containing only the permitted characters.</returns>
        public string Filter(string validChars) => this.Filter(validChars, true);

        /// <summary>Given an array valid characters, filters all non-matching (case-insensitive) characters out of a string.</summary>
        /// <param name="validChars">An array of valid (permitted) characters to retain.</param>
        /// <returns>A string containing only the permitted characters.</returns>
        public string Filter(char[] validChars) => this.Filter(new string(validChars), true);

        /// <summary>Given an array valid characters, filters all non-matching characters out of a string.</summary>
        /// <param name="validChars">An array of valid (permitted) characters to retain.</param>
        /// <param name="ignoreCase">Specifies whether case should be ignored.</param>
        /// <returns>A string containing only the permitted characters.</returns>
        public string Filter(char[] validChars, bool ignoreCase) => this.Filter(new string(validChars), ignoreCase);


        public static implicit operator string(PolyVar data) => data.Value;
        public static implicit operator PolyVar(string data) => new PolyVar(data);

        public static implicit operator int(PolyVar data) => data.ConvertToNbr<int>();
        public static implicit operator PolVar(int data) => new PolyVar(data);

        public static implicit operator sbyte(PolyVar data) => data.ConvertToNbr<sbyte>();
        public static implicit operator PolyVar(sbyte data) => new PolyVar(data);

        public static implicit operator short(PolyVar data) => data.ConvertToNbr<short>();
        public static implicit operator PolyVar(short data) => new PolyVar(data);

        public static implicit operator long(PolyVar data) => data.ConvertToNbr<long>();
        public static implicit operator PolyVar(long data) => new PolyVar(data);

        public static implicit operator decimal(PolyVar data) => data.ConvertToNbr<decimal>();
        public static implicit operator PolyVar(decimal data) => new PolyVar(data);

        public static implicit operator float(PolyVar data) => data.ConvertToNbr<float>();
        public static implicit operator PolyVar(float data) => new PolyVar(data);

        public static implicit operator double(PolyVar data) => data.ConvertToNbr<double>();
        public static implicit operator PolyVar(double data) => new PolyVar(data);

        public static implicit operator uint(PolyVar data) => data.ConvertToNbr<uint>();
        public static implicit operator PolyVar(uint data) => new PolyVar(data);

        public static implicit operator byte(PolyVar data) => data.ConvertToNbr<byte>();
        public static implicit operator PolyVar(byte data) => new PolyVar(data);

        public static implicit operator ulong(PolyVar data) => data.ConvertToNbr<ulong>();
        public static implicit operator PolyVar(ulong data) => new PolyVar(data);

        public static implicit operator ushort(PolyVar data) => data.ConvertToNbr<ushort>();
        public static implicit operator PolyVar(ushort data) => new PolyVar(data);

        public static implicit operator bool(PolyVar data) => data.AsBool;
        public static implicit operator PolyVar(bool data) => new PolyVar(data);

        public static implicit operator XmlDocument(PolyVar data) => data.AsXmlDocument;
        public static implicit operator PolyVar(XmlDocument data) => new PolyVar(data);

        public static implicit operator XmlElement(PolyVar data) => data.AsXmlElement;
        public static implicit operator PolyVar(XmlElement data) => new PolyVar(data);

        public override string ToString() => this._value;

        public override bool Equals(object obj) => this._value.Equals(obj);

        public override int GetHashCode() => this._value.GetHashCode();

        public IEnumerator<char> GetEnumerator() => this._value.GetEnumerator();

        bool IEnumerator.MoveNext() => (++this._position) < this._value.Length;

        void IEnumerator.Reset() => this._position = 0;

        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: dispose managed state (managed objects).
                }

                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.

                disposedValue = true;
            }
        }

        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
        // ~AppletParameters() {
        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        //   Dispose(false);
        // }

        // This code added to correctly implement the disposable pattern.
        void IDisposable.Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
            // TODO: uncomment the following line if the finalizer is overridden above.
            // GC.SuppressFinalize(this);
        }
        #endregion
        #endregion
    }
}
相关问题