mirror of
https://github.com/opensim/opensim.git
synced 2026-08-05 08:55:56 +08:00
* Initial commit of the slimupdates2 rewrite. This pass maintains the original behavior of avatar update sending and has a simplified set of IClientAPI methods for sending avatar/prim updates
This commit is contained in:
@@ -571,207 +571,6 @@ namespace OpenSim.Framework
|
||||
public float dwell;
|
||||
}
|
||||
|
||||
public struct SendAvatarData
|
||||
{
|
||||
public readonly ulong RegionHandle;
|
||||
public readonly string FirstName;
|
||||
public readonly string LastName;
|
||||
public readonly string GroupTitle;
|
||||
public readonly UUID AvatarID;
|
||||
public readonly uint AvatarLocalID;
|
||||
public readonly Vector3 Position;
|
||||
public readonly byte[] TextureEntry;
|
||||
public readonly uint ParentID;
|
||||
public readonly Quaternion Rotation;
|
||||
|
||||
public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID,
|
||||
uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation)
|
||||
{
|
||||
RegionHandle = regionHandle;
|
||||
FirstName = firstName;
|
||||
LastName = lastName;
|
||||
GroupTitle = groupTitle;
|
||||
AvatarID = avatarID;
|
||||
AvatarLocalID = avatarLocalID;
|
||||
Position = position;
|
||||
TextureEntry = textureEntry;
|
||||
ParentID = parentID;
|
||||
Rotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SendAvatarTerseData
|
||||
{
|
||||
public readonly ulong RegionHandle;
|
||||
public readonly ushort TimeDilation;
|
||||
public readonly uint LocalID;
|
||||
public readonly Vector3 Position;
|
||||
public readonly Vector3 Velocity;
|
||||
public readonly Vector3 Acceleration;
|
||||
public readonly Quaternion Rotation;
|
||||
public readonly Vector4 CollisionPlane;
|
||||
public readonly UUID AgentID;
|
||||
public readonly byte[] TextureEntry;
|
||||
public readonly double Priority;
|
||||
|
||||
public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity,
|
||||
Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority)
|
||||
{
|
||||
RegionHandle = regionHandle;
|
||||
TimeDilation = timeDilation;
|
||||
LocalID = localID;
|
||||
Position = position;
|
||||
Velocity = velocity;
|
||||
Acceleration = acceleration;
|
||||
Rotation = rotation;
|
||||
CollisionPlane = collisionPlane;
|
||||
AgentID = agentid;
|
||||
TextureEntry = textureEntry;
|
||||
Priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SendPrimitiveTerseData
|
||||
{
|
||||
public readonly ulong RegionHandle;
|
||||
public readonly ushort TimeDilation;
|
||||
public readonly uint LocalID;
|
||||
public readonly Vector3 Position;
|
||||
public readonly Quaternion Rotation;
|
||||
public readonly Vector3 Velocity;
|
||||
public readonly Vector3 Acceleration;
|
||||
public readonly Vector3 AngularVelocity;
|
||||
public readonly UUID AssetID;
|
||||
public readonly UUID OwnerID;
|
||||
public readonly int AttachPoint;
|
||||
public readonly byte[] TextureEntry;
|
||||
public readonly double Priority;
|
||||
|
||||
public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
|
||||
Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity,
|
||||
UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority)
|
||||
{
|
||||
RegionHandle = regionHandle;
|
||||
TimeDilation = timeDilation;
|
||||
LocalID = localID;
|
||||
Position = position;
|
||||
Rotation = rotation;
|
||||
Velocity = velocity;
|
||||
Acceleration = acceleration;
|
||||
AngularVelocity = rotationalvelocity;
|
||||
AssetID = assetID;
|
||||
OwnerID = ownerID;
|
||||
AttachPoint = attachPoint;
|
||||
TextureEntry = textureEntry;
|
||||
Priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SendPrimitiveData
|
||||
{
|
||||
private ulong m_regionHandle;
|
||||
private ushort m_timeDilation;
|
||||
private uint m_localID;
|
||||
private PrimitiveBaseShape m_primShape;
|
||||
private Vector3 m_pos;
|
||||
private Vector3 m_vel;
|
||||
private Vector3 m_acc;
|
||||
private Quaternion m_rotation;
|
||||
private Vector3 m_rvel;
|
||||
private PrimFlags m_flags;
|
||||
private UUID m_objectID;
|
||||
private UUID m_ownerID;
|
||||
private string m_text;
|
||||
private byte[] m_color;
|
||||
private uint m_parentID;
|
||||
private byte[] m_particleSystem;
|
||||
private byte m_clickAction;
|
||||
private byte m_material;
|
||||
private byte[] m_textureanim;
|
||||
private bool m_attachment;
|
||||
private uint m_AttachPoint;
|
||||
private UUID m_AssetId;
|
||||
private UUID m_SoundId;
|
||||
private double m_SoundVolume;
|
||||
private byte m_SoundFlags;
|
||||
private double m_SoundRadius;
|
||||
private double m_priority;
|
||||
|
||||
public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
|
||||
Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
|
||||
uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
|
||||
uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) :
|
||||
this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID,
|
||||
ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero,
|
||||
UUID.Zero, 0, 0, 0, priority) { }
|
||||
|
||||
public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
|
||||
Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
|
||||
uint flags,
|
||||
UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
|
||||
byte[] particleSystem,
|
||||
byte clickAction, byte material, byte[] textureanim, bool attachment,
|
||||
uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
|
||||
double SoundRadius, double priority)
|
||||
{
|
||||
this.m_regionHandle = regionHandle;
|
||||
this.m_timeDilation = timeDilation;
|
||||
this.m_localID = localID;
|
||||
this.m_primShape = primShape;
|
||||
this.m_pos = pos;
|
||||
this.m_vel = vel;
|
||||
this.m_acc = acc;
|
||||
this.m_rotation = rotation;
|
||||
this.m_rvel = rvel;
|
||||
this.m_flags = (PrimFlags)flags;
|
||||
this.m_objectID = objectID;
|
||||
this.m_ownerID = ownerID;
|
||||
this.m_text = text;
|
||||
this.m_color = color;
|
||||
this.m_parentID = parentID;
|
||||
this.m_particleSystem = particleSystem;
|
||||
this.m_clickAction = clickAction;
|
||||
this.m_material = material;
|
||||
this.m_textureanim = textureanim;
|
||||
this.m_attachment = attachment;
|
||||
this.m_AttachPoint = AttachPoint;
|
||||
this.m_AssetId = AssetId;
|
||||
this.m_SoundId = SoundId;
|
||||
this.m_SoundVolume = SoundVolume;
|
||||
this.m_SoundFlags = SoundFlags;
|
||||
this.m_SoundRadius = SoundRadius;
|
||||
this.m_priority = priority;
|
||||
}
|
||||
|
||||
public ulong regionHandle { get { return this.m_regionHandle; } }
|
||||
public ushort timeDilation { get { return this.m_timeDilation; } }
|
||||
public uint localID { get { return this.m_localID; } }
|
||||
public PrimitiveBaseShape primShape { get { return this.m_primShape; } }
|
||||
public Vector3 pos { get { return this.m_pos; } }
|
||||
public Vector3 vel { get { return this.m_vel; } }
|
||||
public Vector3 acc { get { return this.m_acc; } }
|
||||
public Quaternion rotation { get { return this.m_rotation; } }
|
||||
public Vector3 rvel { get { return this.m_rvel; } }
|
||||
public PrimFlags flags { get { return this.m_flags; } }
|
||||
public UUID objectID { get { return this.m_objectID; } }
|
||||
public UUID ownerID { get { return this.m_ownerID; } }
|
||||
public string text { get { return this.m_text; } }
|
||||
public byte[] color { get { return this.m_color; } }
|
||||
public uint parentID { get { return this.m_parentID; } }
|
||||
public byte[] particleSystem { get { return this.m_particleSystem; } }
|
||||
public byte clickAction { get { return this.m_clickAction; } }
|
||||
public byte material { get { return this.m_material; } }
|
||||
public byte[] textureanim { get { return this.m_textureanim; } }
|
||||
public bool attachment { get { return this.m_attachment; } }
|
||||
public uint AttachPoint { get { return this.m_AttachPoint; } }
|
||||
public UUID AssetId { get { return this.m_AssetId; } }
|
||||
public UUID SoundId { get { return this.m_SoundId; } }
|
||||
public double SoundVolume { get { return this.m_SoundVolume; } }
|
||||
public byte SoundFlags { get { return this.m_SoundFlags; } }
|
||||
public double SoundRadius { get { return this.m_SoundRadius; } }
|
||||
public double priority { get { return this.m_priority; } }
|
||||
}
|
||||
|
||||
public struct UpdatePriorityData {
|
||||
private double m_priority;
|
||||
private uint m_localID;
|
||||
@@ -785,14 +584,46 @@ namespace OpenSim.Framework
|
||||
public uint localID { get { return this.m_localID; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the fields that have been changed when sending a prim or
|
||||
/// avatar update
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum StateUpdateTypes
|
||||
public enum PrimUpdateFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
AvatarTerse = 1,
|
||||
PrimitiveTerse = AvatarTerse << 1,
|
||||
PrimitiveFull = PrimitiveTerse << 1,
|
||||
All = AvatarTerse | PrimitiveTerse | PrimitiveFull,
|
||||
AttachmentPoint = 1 << 0,
|
||||
Material = 1 << 1,
|
||||
ClickAction = 1 << 2,
|
||||
Scale = 1 << 3,
|
||||
ParentID = 1 << 4,
|
||||
PrimFlags = 1 << 5,
|
||||
PrimData = 1 << 6,
|
||||
MediaURL = 1 << 7,
|
||||
ScratchPad = 1 << 8,
|
||||
Textures = 1 << 9,
|
||||
TextureAnim = 1 << 10,
|
||||
NameValue = 1 << 11,
|
||||
Position = 1 << 12,
|
||||
Rotation = 1 << 13,
|
||||
Velocity = 1 << 14,
|
||||
Acceleration = 1 << 15,
|
||||
AngularVelocity = 1 << 16,
|
||||
CollisionPlane = 1 << 17,
|
||||
Text = 1 << 18,
|
||||
Particles = 1 << 19,
|
||||
ExtraData = 1 << 20,
|
||||
Sound = 1 << 21,
|
||||
Joint = 1 << 22,
|
||||
FullUpdate = UInt32.MaxValue
|
||||
}
|
||||
|
||||
public static class PrimUpdateFlagsExtensions
|
||||
{
|
||||
public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag)
|
||||
{
|
||||
return (updateFlags & flag) == flag;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IClientAPI
|
||||
@@ -1186,27 +1017,20 @@ namespace OpenSim.Framework
|
||||
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
|
||||
void SendPayPrice(UUID objectID, int[] payPrice);
|
||||
|
||||
void SendAvatarData(SendAvatarData data);
|
||||
|
||||
void SendAvatarTerseUpdate(SendAvatarTerseData data);
|
||||
|
||||
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
|
||||
|
||||
void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
|
||||
void SetChildAgentThrottle(byte[] throttle);
|
||||
|
||||
void SendPrimitiveToClient(SendPrimitiveData data);
|
||||
|
||||
void SendPrimTerseUpdate(SendPrimitiveTerseData data);
|
||||
|
||||
void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
|
||||
void SendAvatarDataImmediate(ISceneEntity avatar);
|
||||
void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
|
||||
void ReprioritizeUpdates(UpdatePriorityHandler handler);
|
||||
void FlushPrimUpdates();
|
||||
|
||||
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
|
||||
List<InventoryFolderBase> folders, int version, bool fetchFolders,
|
||||
bool fetchItems);
|
||||
|
||||
void FlushPrimUpdates();
|
||||
|
||||
void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item);
|
||||
|
||||
/// <summary>
|
||||
|
||||
37
OpenSim/Framework/ISceneEntity.cs
Normal file
37
OpenSim/Framework/ISceneEntity.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public interface ISceneEntity
|
||||
{
|
||||
UUID UUID { get; }
|
||||
uint LocalId { get; }
|
||||
}
|
||||
}
|
||||
236
OpenSim/Framework/Lazy.cs
Normal file
236
OpenSim/Framework/Lazy.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// Lazy.cs
|
||||
//
|
||||
// Authors:
|
||||
// Zoltan Varga (vargaz@gmail.com)
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2009 Novell
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public enum LazyThreadSafetyMode
|
||||
{
|
||||
None,
|
||||
PublicationOnly,
|
||||
ExecutionAndPublication
|
||||
}
|
||||
|
||||
[SerializableAttribute]
|
||||
[ComVisibleAttribute(false)]
|
||||
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
|
||||
public class Lazy<T>
|
||||
{
|
||||
T value;
|
||||
bool inited;
|
||||
LazyThreadSafetyMode mode;
|
||||
Func<T> factory;
|
||||
object monitor;
|
||||
Exception exception;
|
||||
|
||||
public Lazy()
|
||||
: this(LazyThreadSafetyMode.ExecutionAndPublication)
|
||||
{
|
||||
}
|
||||
|
||||
public Lazy(Func<T> valueFactory)
|
||||
: this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
|
||||
{
|
||||
}
|
||||
|
||||
public Lazy(bool isThreadSafe)
|
||||
: this(() => Activator.CreateInstance<T>(), isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
|
||||
{
|
||||
}
|
||||
|
||||
public Lazy(Func<T> valueFactory, bool isThreadSafe)
|
||||
: this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
|
||||
{
|
||||
}
|
||||
|
||||
public Lazy(LazyThreadSafetyMode mode)
|
||||
: this(() => Activator.CreateInstance<T>(), mode)
|
||||
{
|
||||
}
|
||||
|
||||
public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
|
||||
{
|
||||
if (valueFactory == null)
|
||||
throw new ArgumentNullException("valueFactory");
|
||||
this.factory = valueFactory;
|
||||
if (mode != LazyThreadSafetyMode.None)
|
||||
monitor = new object();
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
// Don't trigger expensive initialization
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (inited)
|
||||
return value;
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
|
||||
return InitValue();
|
||||
}
|
||||
}
|
||||
|
||||
T InitValue()
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case LazyThreadSafetyMode.None:
|
||||
{
|
||||
var init_factory = factory;
|
||||
if (init_factory == null)
|
||||
throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
|
||||
try
|
||||
{
|
||||
factory = null;
|
||||
T v = init_factory();
|
||||
value = v;
|
||||
Thread.MemoryBarrier();
|
||||
inited = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LazyThreadSafetyMode.PublicationOnly:
|
||||
{
|
||||
var init_factory = factory;
|
||||
T v;
|
||||
|
||||
//exceptions are ignored
|
||||
if (init_factory != null)
|
||||
v = init_factory();
|
||||
else
|
||||
v = default(T);
|
||||
|
||||
lock (monitor)
|
||||
{
|
||||
if (inited)
|
||||
return value;
|
||||
value = v;
|
||||
Thread.MemoryBarrier();
|
||||
inited = true;
|
||||
factory = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LazyThreadSafetyMode.ExecutionAndPublication:
|
||||
{
|
||||
lock (monitor)
|
||||
{
|
||||
if (inited)
|
||||
return value;
|
||||
|
||||
if (factory == null)
|
||||
throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
|
||||
|
||||
var init_factory = factory;
|
||||
try
|
||||
{
|
||||
factory = null;
|
||||
T v = init_factory();
|
||||
value = v;
|
||||
Thread.MemoryBarrier();
|
||||
inited = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid LazyThreadSafetyMode " + mode);
|
||||
}
|
||||
|
||||
if (monitor == null)
|
||||
{
|
||||
value = factory();
|
||||
inited = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (monitor)
|
||||
{
|
||||
if (inited)
|
||||
return value;
|
||||
|
||||
if (factory == null)
|
||||
throw new InvalidOperationException("The initialization function tries to access Value on this instance");
|
||||
|
||||
var init_factory = factory;
|
||||
try
|
||||
{
|
||||
factory = null;
|
||||
T v = init_factory();
|
||||
value = v;
|
||||
Thread.MemoryBarrier();
|
||||
inited = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
factory = init_factory;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public bool IsValueCreated
|
||||
{
|
||||
get
|
||||
{
|
||||
return inited;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (inited)
|
||||
return value.ToString();
|
||||
else
|
||||
return "Value is not created";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user