এক্সএমএলে একটি টাইমস্প্যানকে কীভাবে সিরিয়ালাইজ করা যায়


206

আমি TimeSpanএক্সএমএলে একটি .NET অবজেক্টটি সিরিয়ালাইজ করার চেষ্টা করছি এবং এটি কাজ করছে না। একটি দ্রুত গুগল পরামর্শ দিয়েছে যে TimeSpanসিরিয়ালাইজ করার সময় , এক্সএমএলে এবং থেকে বস্তুগুলিকে XmlCustomFormatterরূপান্তর করার পদ্ধতি সরবরাহ করে না TimeSpan

প্রস্তাবিত পদ্ধতির একটি ছিল TimeSpanসিরিয়ালাইজেশনের জন্য অগ্রাহ্য করা , এবং পরিবর্তে TimeSpan.Ticks(এবং new TimeSpan(ticks)deserialization জন্য ব্যবহার ) ফলাফল সিরিয়ালাইজ করা । এর একটি উদাহরণ নিম্নলিখিত:

[Serializable]
public class MyClass
{
    // Local Variable
    private TimeSpan m_TimeSinceLastEvent;

    // Public Property - XmlIgnore as it doesn't serialize anyway
    [XmlIgnore]
    public TimeSpan TimeSinceLastEvent
    {
        get { return m_TimeSinceLastEvent; }
        set { m_TimeSinceLastEvent = value; }
    }

    // Pretend property for serialization
    [XmlElement("TimeSinceLastEvent")]
    public long TimeSinceLastEventTicks
    {
        get { return m_TimeSinceLastEvent.Ticks; }
        set { m_TimeSinceLastEvent = new TimeSpan(value); }
    }
}

যদিও এটি আমার সংক্ষিপ্ত পরীক্ষায় কাজ করে বলে মনে হচ্ছে - এটি কি এটি অর্জনের সেরা উপায়?

এক্সএমএল থেকে এবং এর জন্য টাইমস্প্যানকে সিরিয়ালযুক্ত করার আরও ভাল উপায় কি?


4
নীচে ররি ম্যাকলিউডের উত্তরটি মাইক্রোসফ্ট যেভাবে এটি করার পরামর্শ দেয় is
জেফ

2
আমি টাইমস্প্যান্ডের জন্য দীর্ঘ টিক্স ব্যবহার করব না কারণ এক্সএমএলের সময়কাল টাইপ হুবহু মিল। ২০০৮ সালে এই বিষয়টি মাইক্রোসফ্টের কাছে উত্থাপিত হয়েছিল কিন্তু কখনও সমাধান হয়নি। এরপরে একটি কার্যতালিকা
কেনেথ জু

উত্তর:


71

আপনি ইতিমধ্যে যেভাবে পোস্ট করেছেন সম্ভবত এটি সবচেয়ে পরিষ্কার। আপনি অতিরিক্ত সম্পত্তি পছন্দ না হয়, আপনি বাস্তবায়ন হতে পারে IXmlSerializable, কিন্তু তারপর আপনাকে যা করতে হবে সব , যা মূলত বিন্দু ফলে নষ্ট হয়। আমি আপনার পোস্টটি প্রকাশিতভাবে ব্যবহার করব; এটি (উদাহরণস্বরূপ) দক্ষ (জটিল পার্সিং ইত্যাদি নয়), সংস্কৃতি স্বাধীন, দ্ব্যর্থহীন এবং টাইমস্ট্যাম্প-ধরণের সংখ্যাগুলি সহজে এবং সাধারণভাবে বোঝা যায়।

একদিকে যেমন আমি প্রায়শই যুক্ত করি:

[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

বিভ্রান্তি এড়াতে এটি কেবল এটি ইউআই এবং রেফারেন্সিং ডেলসে লুকিয়ে রাখে।


5
এরকম সবকিছু এত খারাপ আপনি একটি struct যে System.TimeSpan গোপন, বরং MyClass তে এটি বাস্তবায়নের চেয়ে ইন্টারফেস বাস্তবায়ন নয়। তারপরে আপনাকে কেবল আপনার মাইক্লাসের টাইপটি পরিবর্তন করতে হবে ime টাইমসিন্সস্টাস্ট লাস্ট ইভেন্ট সম্পত্তি
ফগ

103

প্রশ্নটিতে প্রস্তাবিত পদ্ধতির ক্ষেত্রে এটি কেবলমাত্র একটি সামান্য পরিবর্তন, তবে এই মাইক্রোসফ্ট কানেক্ট ইস্যুটি সিরিয়ালাইজেশনের জন্য কোনও সম্পত্তি ব্যবহার করার পরামর্শ দেয়:

[XmlIgnore]
public TimeSpan TimeSinceLastEvent
{
    get { return m_TimeSinceLastEvent; }
    set { m_TimeSinceLastEvent = value; }
}

// XmlSerializer does not support TimeSpan, so use this property for 
// serialization instead.
[Browsable(false)]
[XmlElement(DataType="duration", ElementName="TimeSinceLastEvent")]
public string TimeSinceLastEventString
{
    get 
    { 
        return XmlConvert.ToString(TimeSinceLastEvent); 
    }
    set 
    { 
        TimeSinceLastEvent = string.IsNullOrEmpty(value) ?
            TimeSpan.Zero : XmlConvert.ToTimeSpan(value); 
    }
}

এটি 0:02:45 এর টাইমস্প্যানটি সিরিয়ালিয়াল করবে:

<TimeSinceLastEvent>PT2M45S</TimeSinceLastEvent>

বিকল্পভাবে, DataContractSerializerটাইমস্প্যান সমর্থন করে।


15
এক্সএমএল কনভার্ট.টোটাইমস্প্যান () এর জন্য +1। এটা তোলে PT2H15M মত timespan জন্য ISO- র মান সময়কাল সিনট্যাক্স পরিচালনা দেখুন en.wikipedia.org/wiki/ISO_8601#Durations
yzorg

2
আমি ভুল হলে আমাকে সংশোধন করুন, তবে সেরেলাইজড টাইমস্প্যান "পিটি 2 এম 45 এস" হল 00:02:45, 2:45:00 নয়।
টম পাউরেক

সংযোগ লিঙ্কটি এখন ভেঙে গেছে, সম্ভবত এটির সাথে এটি প্রতিস্থাপন করা যেতে পারে: সংযুক্ত.মাইক্রোসফট / ভিজুয়ালস্টুডিও / ফেডব্যাক / বিবরণ / 48৮৮৮৯৯/ / ?
কৌশলটিও

অনুসরণ করার একটি অদ্ভুত প্রশ্ন, এসকিউএল-তে টাইম টু পিটি 2 এম 45 এস এই মানটি ডিসিশায়াল করার কী আমাদের কোনও উপায় আছে?
Xender

28

কিছু ক্ষেত্রে কাজ করতে পারে এমন কিছু হ'ল আপনার সর্বজনীন সম্পত্তিকে একটি ব্যাকিং ফিল্ড দেওয়া, যা একটি টাইমস্প্যান, তবে সর্বজনীন সম্পত্তি একটি স্ট্রিং হিসাবে প্রকাশিত হয়।

উদাহরণ:

protected TimeSpan myTimeout;
public string MyTimeout 
{ 
    get { return myTimeout.ToString(); } 
    set { myTimeout = TimeSpan.Parse(value); }
}

এটি ঠিক আছে যদি সম্পত্তির মানটি বেশিরভাগ ডাব্লু / সমেত শ্রেণি বা উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাসে ব্যবহৃত হয় এবং এক্সএমএল কনফিগারেশন থেকে লোড হয়।

অন্যান্য প্রস্তাবিত সমাধানগুলি আরও ভাল যদি আপনি সর্বজনীন সম্পত্তি অন্যান্য শ্রেণীর জন্য ব্যবহারযোগ্য টাইমস্প্যান মান হতে চান।


এখনও পর্যন্ত সবচেয়ে সহজ সমাধান। আমি ঠিক একই জিনিসটি নিয়ে এসেছি এবং এটি একটি কবজির মতো কাজ করে। কার্যকর এবং বুঝতে সহজ।
wpfwannabe

1
এটি এখানে সেরা সমাধান। এটি খুব ভাল সিরিয়ালাইজ !!! বন্ধু ইনপুট জন্য আপনাকে ধন্যবাদ!
বিকাশকারী

25

রঙিন সিরিয়ালাইজেশন এবং এই মূল সমাধানটি (যা নিজেই দুর্দান্ত) এর একটি উত্তর মিশ্রণ করে আমি এই সমাধান পেয়েছি:

[XmlElement(Type = typeof(XmlTimeSpan))]
public TimeSpan TimeSinceLastEvent { get; set; }

XmlTimeSpanক্লাস যেখানে এই মত:

public class XmlTimeSpan
{
    private const long TICKS_PER_MS = TimeSpan.TicksPerMillisecond;

    private TimeSpan m_value = TimeSpan.Zero;

    public XmlTimeSpan() { }
    public XmlTimeSpan(TimeSpan source) { m_value = source; }

    public static implicit operator TimeSpan?(XmlTimeSpan o)
    {
        return o == null ? default(TimeSpan?) : o.m_value;
    }

    public static implicit operator XmlTimeSpan(TimeSpan? o)
    {
        return o == null ? null : new XmlTimeSpan(o.Value);
    }

    public static implicit operator TimeSpan(XmlTimeSpan o)
    {
        return o == null ? default(TimeSpan) : o.m_value;
    }

    public static implicit operator XmlTimeSpan(TimeSpan o)
    {
        return o == default(TimeSpan) ? null : new XmlTimeSpan(o);
    }

    [XmlText]
    public long Default
    {
        get { return m_value.Ticks / TICKS_PER_MS; }
        set { m_value = new TimeSpan(value * TICKS_PER_MS); }
    }
}

এই সমস্যাটি সমাধান করার সর্বোত্তম এবং সহজ উপায় ... আমার জন্য
মোরারু ভাইরেল

এটি একেবারে বুদ্ধিমান - আমি খুব মুগ্ধ!
জিম

9

আপনি টাইমস্প্যান কাঠামোর চারপাশে একটি হালকা মোড়ক তৈরি করতে পারেন:

namespace My.XmlSerialization
{
    public struct TimeSpan : IXmlSerializable
    {
        private System.TimeSpan _value;

        public static implicit operator TimeSpan(System.TimeSpan value)
        {
            return new TimeSpan { _value = value };
        }

        public static implicit operator System.TimeSpan(TimeSpan value)
        {
            return value._value;
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            _value = System.TimeSpan.Parse(reader.ReadContentAsString());
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteValue(_value.ToString());
        }
    }
}

নমুনা সিরিয়ালযুক্ত ফলাফল:

<Entry>
  <StartTime>2010-12-06T08:45:12.5</StartTime>
  <Duration>2.08:29:35.2500000</Duration>
</Entry>

XMLAttribute হিসাবে আউটপুটটি কীভাবে তৈরি করবেন কোনও ধারণা?
আলা

@ আলা, আমি যদি আপনার প্রশ্নটি সঠিকভাবে বুঝতে পারি তবে এর উত্তরটি হ'ল আপনি যে বৈশিষ্ট্যটি কোনও বৈশিষ্ট্য হিসাবে প্রকাশ করতে চান তার XMLAttributeAttribute প্রয়োগ করা। এটি অবশ্যই টাইমস্প্যানের পক্ষে বিশেষ নয়।
ফুগ

+1 সুন্দর, আমি এটিকে স্ট্রিং হিসাবে নয় তবে Ticksদীর্ঘায়িত করব।
ক্রিসউইউ

@ ক্রিসউইউ আমার অফিসে আমরা এক্সএমএল সিরিয়ালাইজেশন ব্যবহার করি যখন আমরা মানব-পঠনযোগ্য আউটপুট চাই; একটি টাইমস্প্যানকে দীর্ঘ হিসাবে সিরিয়াল করা সেই লক্ষ্যের সাথে বেশ উপযুক্ত নয়। আপনি যদি অন্য কোনও কারণে এক্সএমএল সিরিয়ালাইজেশন ব্যবহার করেন তবে অবশ্যই টিকগুলি সিরিয়াল করা আরও বোধগম্য হতে পারে।
ফোগ

8

আরও পঠনযোগ্য বিকল্প TimeSpan.Parseহ'ল স্ট্রিং হিসাবে সিরিয়ালাইজ করা এবং এটিকে deserialize করার পদ্ধতিটি ব্যবহার করা। আপনি নিজের উদাহরণ হিসাবে একই কাজ করতে পারেন তবে TimeSpan.ToString()গিটার এবং সেটারে ব্যবহার করে TimeSpan.Parse(value)


2

SoapFormatterক্লাসের পরিবর্তে ক্লাস ব্যবহার করে এটির ক্রিয়াকলাপ করা অন্য বিকল্প হবে XmlSerializer

ফলাফলের এক্সএমএল ফাইলটি দেখতে অন্যরকম দেখাচ্ছে ... কিছু "এসওএপি" - পূর্বনির্ধারিত ট্যাগগুলি ইত্যাদি ... তবে এটি এটি করতে পারে।

এখানে SoapFormatter20 ঘন্টা এবং 28 মিনিটের টাইমস্প্যানকে সিরিয়ালযুক্ত করা হয়েছে তা এখানে:

<myTimeSpan>P0Y0M0DT20H28M0S</myTimeSpan>

এসওএপি ফরম্যাটার ক্লাসটি System.Runtime.Serialization.Formatters.Soapব্যবহার করতে, একই নামের রেফারেন্স যুক্ত করতে হবে এবং ব্যবহার করতে হবে।


নেট নেট 4.0.০
ক্রিক ব্রডহর্স্ট

1

সমাধানটির আমার সংস্করণ :)

[DataMember, XmlIgnore]
public TimeSpan MyTimeoutValue { get; set; }
[DataMember]
public string MyTimeout
{
    get { return MyTimeoutValue.ToString(); }
    set { MyTimeoutValue = TimeSpan.Parse(value); }
}

সম্পাদনা: ধরে নেওয়া যায় এটি অবিচ্ছেদ্য ...

[DataMember, XmlIgnore]
public TimeSpan? MyTimeoutValue { get; set; }
[DataMember]
public string MyTimeout
{
    get 
    {
        if (MyTimeoutValue != null)
            return MyTimeoutValue.ToString();
        return null;
    }
    set 
    {
        TimeSpan outValue;
        if (TimeSpan.TryParse(value, out outValue))
            MyTimeoutValue = outValue;
        else
            MyTimeoutValue = null;
    }
}

1

টাইমস্প্যানটি সেকেন্ডের সংখ্যা হিসাবে এক্সএমএলে সঞ্চিত, তবে এটি গ্রহণ করা সহজ, আমি আশা করি। টাইমস্প্যানটি ম্যানুয়ালি সিরিয়ালাইজড হয়েছে (আইএক্সএমএল সিরিয়ালাইজেশন বাস্তবায়ন করা):

public class Settings : IXmlSerializable
{
    [XmlElement("IntervalInSeconds")]
    public TimeSpan Interval;

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("IntervalInSeconds", ((int)Interval.TotalSeconds).ToString());
    }

    public void ReadXml(XmlReader reader)
    {
        string element = null;
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
                element = reader.Name;
            else if (reader.NodeType == XmlNodeType.Text)
            {
                if (element == "IntervalInSeconds")
                    Interval = TimeSpan.FromSeconds(double.Parse(reader.Value.Replace(',', '.'), CultureInfo.InvariantCulture));
            }
       }
    }
}

এর আরও বিস্তৃত উদাহরণ রয়েছে: https://bitbucket.org/njkazakov/imespan-seialization

Settings.cs এ দেখুন। এবং এক্সএমএলএমেন্টএট্রিবিউট ব্যবহার করার জন্য কিছু কৌশলযুক্ত কোড রয়েছে।


1
দয়া করে সেই লিঙ্ক থেকে প্রাসঙ্গিক তথ্য উদ্ধৃত করুন। আপনার উত্তরের জন্য প্রয়োজনীয় সমস্ত তথ্য এই সাইটে থাকা উচিত এবং তারপরে আপনি সেই লিঙ্কটিকে উত্স হিসাবে উদ্ধৃত করতে পারেন।
সুপারবিসাইডম্যান

0

ডেটা কন্ট্রাক্ট সিরিয়ালের জন্য আমি নিম্নলিখিতটি ব্যবহার করি।

  • সিরিয়ালযুক্ত সম্পত্তিটি ব্যক্তিগত রাখা জনসাধারণের ইন্টারফেসকে পরিষ্কার রাখে।
  • সিরিয়ালাইজেশনের জন্য সর্বজনীন সম্পত্তি নাম ব্যবহার করা এক্সএমএল পরিষ্কার রাখে।
Public Property Duration As TimeSpan

<DataMember(Name:="Duration")>
Private Property DurationString As String
    Get
        Return Duration.ToString
    End Get
    Set(value As String)
        Duration = TimeSpan.Parse(value)
    End Set
End Property

0

আপনি যদি কোনও কাজের ভিত্তি না চান তবে সিস্টেম.আরটাইম.সরিয়ালাইজেশন.ডিল থেকে ডেটা কন্ট্রাক্টসরিয়ালাইজ ক্লাসটি ব্যবহার করুন।

        using (var fs = new FileStream("file.xml", FileMode.Create))
        {
            var serializer = new DataContractSerializer(typeof(List<SomeType>));
            serializer.WriteObject(fs, _items);
        }

-2

এটা চেষ্টা কর :

//Don't Serialize Time Span object.
        [XmlIgnore]
        public TimeSpan m_timeSpan;
//Instead serialize (long)Ticks and instantiate Timespan at time of deserialization.
        public long m_TimeSpanTicks
        {
            get { return m_timeSpan.Ticks; }
            set { m_timeSpan = new TimeSpan(value); }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.