I am writing a plugin where I check if a particular value of a field, an Option Set is equal to a specific value and if so, then I do certain actions.
Now, within the plugin C# code, how can I check that the Option Set field is not null - i.e., is set to the Default Value?
What I did (clearly, that is wrong) because, it never went past the Null check statement. And, if I did not have the check, then I get this error message
Error:
Unexpected exception from plug-in (Execute): CRM.AppStateHandler.Plugins.PostApplicationCreate: System.NullReferenceException: Object reference not set to an instance of an object.
Code:
application applicationEntity = entity.ToEntity<new_application>();
if (new_applicationEntity.new_Applicationstatus != null)
{
var applicationStatus = applicationEntity.new_Applicationstatus.Value;
if (applicationStatus == CRMConstants.EntityApplication.Attributes.ApplicationStatusOptions.Applying)
{
//my logic
}
}
File constants.cs has the following
class CRMConstants
{
public struct EntityApplication
{
public struct Attributes
{
public struct ApplicationStatusOptions
{
// More before this
public const int Applying = 100000006;
// More to come
}
}
}
I think SergeyS has your fix, but I'll add some other (hopefully) helpful comments.
Don't custom create structs for your Option Set Values. Use the CrmSrvcUtil to create enums for you automatically.
I get annoyed with having to check for OptionSetValues being null or not, so I use these extension methods to make my life easier:
/// <summary>
/// Returns the value of the OptionSetValue, or int.MinValue if it is null
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int GetValueOrDefault(this OptionSetValue osv)
{
return GetValueOrDefault(osv, int.MinValue);
}
/// <summary>
/// Returns the value of the OptionSetValue, or int.MinValue if it is null
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int GetValueOrDefault(this OptionSetValue osv, int defaultValue)
{
if (osv == null)
{
return defaultValue;
}
else
{
return osv.Value;
}
}
/// <summary>
/// Allows for Null safe Equals Comparison for more concise code. ie.
/// if(contact.GenderCode.NullSafeEquals(1))
/// vs.
/// if(contact.GenderCode != null && contact.gendercode.Value == 1)
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool NullSafeEquals(this OptionSetValue osv, int value)
{
if (osv == null)
{
return false;
}
else
{
return osv.Value == value;
}
}
/// <summary>
/// Allows for Null safe Equals Comparison for more concise code. ie.
/// if(contact.GenderCode.NullSafeEquals(new OptionSet(1)))
/// vs.
/// if(contact.GenderCode != null && contact.gendercode.Value == new OptionSet(1))
/// </summary>
/// <param name="osv"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool NullSafeEquals(this OptionSetValue osv, OptionSetValue value)
{
if (osv == null)
{
return osv == value;
}
else
{
return osv.Equals(value);
}
}
There are two methods each with an overload:
GetValueOrDefault - This is equivalent to the Nullable.GetValueOrDefault(). The one difference is rather than defaulting to 0, I default to int.MinValue to make sure I don't accidentally match on a 0 optionset value. The Overload allows you to specify the default value if you'd like.
NullSafeEquals - This is the one you'd be using in your code to not have to check for null
application applicationEntity = entity.ToEntity<new_application>();
if (applicationEntity.new_Applicationstatus.NullSafeEquals(CRMConstants.EntityApplication.Attributes.ApplicationStatusOptions.Applying))
{
//my logic
}
You are checking:
if (new_applicationEntity.new_Applicationstatus != null)
but you need to check:
if (applicationEntity.new_Applicationstatus != null)
Related
In unity I keep on getting this error that keeps on bugging me, I tried to remove packages to leave one of these errors and it kept on going on and on, i am developing a game right now using unity engine and the errors are a big pain for me, this is the code that someone asked for, i dont really have much else to write other than this, stackoverlow isnt letting me just post it because its too short
using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.SettingsManagement
{
/// <inheritdoc />
/// <summary>
/// A settings repository that stores data local to a Unity project.
/// </summary>
[Serializable]
public sealed class PackageSettingsRepository : ISettingsRepository
{
const string k_PackageSettingsDirectory = "ProjectSettings/Packages";
const bool k_PrettyPrintJson = true;
bool m_Initialized;
[SerializeField]
string m_Name;
[SerializeField]
string m_Path;
[SerializeField]
SettingsDictionary m_Dictionary = new SettingsDictionary();
/// <summary>
/// Constructor sets the serialized data path.
/// </summary>
/// <param name="package">
/// The package name.
/// </param>
/// <param name="name">
/// A name for this settings file. Settings are saved in `ProjectSettings/Packages/{package}/{name}.json`.
/// </param>
public PackageSettingsRepository(string package, string name)
{
m_Name = name;
m_Path = GetSettingsPath(package, name);
m_Initialized = false;
AssemblyReloadEvents.beforeAssemblyReload += Save;
EditorApplication.quitting += Save;
}
void Init()
{
if (m_Initialized)
return;
m_Initialized = true;
if (File.Exists(path))
{
m_Dictionary = null;
var json = File.ReadAllText(path);
EditorJsonUtility.FromJsonOverwrite(json, this);
if(m_Dictionary == null)
m_Dictionary = new SettingsDictionary();
}
}
/// <value>
/// This repository implementation is relevant to the Project scope.
/// </value>
/// <inheritdoc cref="ISettingsRepository.scope"/>
public SettingsScope scope
{
get { return SettingsScope.Project; }
}
/// <value>
/// The full path to the settings file.
/// This corresponds to `Unity Project/Project Settings/Packages/com.unity.package/name`.
/// </value>
/// <inheritdoc cref="ISettingsRepository.path"/>
public string path
{
get { return m_Path; }
}
/// <summary>
/// The name of this settings file.
/// </summary>
public string name
{
get { return m_Name; }
}
// Cannot call FindFromAssembly from a constructor or field initializer
// static string CreateSettingsPath(Assembly assembly, string name)
// {
// var info = PackageManager.PackageInfo.FindForAssembly(assembly);
// return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, info.name, name);
// }
/// <summary>
/// Get a path for a settings file relative to the calling assembly package directory.
/// </summary>
/// <param name="packageName">The name of the package requesting this setting.</param>
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
/// <returns>A package-scoped path to the settings file within Project Settings.</returns>
public static string GetSettingsPath(string packageName, string name = "Settings")
{
return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name);
}
/// <summary>
/// Save all settings to their serialized state.
/// </summary>
/// <inheritdoc cref="ISettingsRepository.Save"/>
public void Save()
{
Init();
if (!File.Exists(path))
{
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
}
#if UNITY_2019_3_OR_NEWER
if (!AssetDatabase.IsOpenForEdit(path))
{
if (!AssetDatabase.MakeEditable(path))
{
Debug.LogWarning($"Could not save package settings to {path}");
return;
}
}
#endif
try
{
File.WriteAllText(path, EditorJsonUtility.ToJson(this, k_PrettyPrintJson));
}
catch (UnauthorizedAccessException)
{
Debug.LogWarning($"Could not save package settings to {path}");
}
}
/// <summary>
/// Set a value for key of type T.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="value">The value to set. Must be serializable.</param>
/// <typeparam name="T">Type of value.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Set{T}"/>
public void Set<T>(string key, T value)
{
Init();
m_Dictionary.Set<T>(key, value);
}
/// <summary>
/// Get a value with key of type T, or return the fallback value if no matching key is found.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="fallback">If no key with a value of type T is found, this value is returned.</param>
/// <typeparam name="T">Type of value to search for.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Get{T}"/>
public T Get<T>(string key, T fallback = default(T))
{
Init();
return m_Dictionary.Get<T>(key, fallback);
}
/// <summary>
/// Does the repository contain a setting with key and type.
/// </summary>
/// <param name="key">The settings key.</param>
/// <typeparam name="T">The type of value to search for.</typeparam>
/// <returns>True if a setting matching both key and type is found, false if no entry is found.</returns>
/// <inheritdoc cref="ISettingsRepository.ContainsKey{T}"/>
public bool ContainsKey<T>(string key)
{
Init();
return m_Dictionary.ContainsKey<T>(key);
}
/// <summary>
/// Remove a key value pair from the settings repository.
/// </summary>
/// <param name="key"></param>
/// <typeparam name="T"></typeparam>
/// <inheritdoc cref="ISettingsRepository.Remove{T}"/>
public void Remove<T>(string key)
{
Init();
m_Dictionary.Remove<T>(key);
By the definition of 'RequestScriptReload' :
"The Unity Editor reloads script assemblies asynchronously on the next frame. This resets the state of all the scripts, but Unity does not compile any code that has changed since the previous compilation."
That means that your problem is probably with something that you changed.
You can try:
Going back to the last time everything wored and go on from there.
Closing all of you unity and scripting applications and opening it again.
When I remove objects from the list the UI doesn't reflect the current state of the list, normally failling by only one item.
Example: If I remove 4 items, on the UI only shows that I removed 3 items
private ObservableCollection<Card> _cards;
public ObservableCollection<Card> Cards
{
get
{
if (_cards == null)
{
_cards = new ObservableCollection<Card>();
return _cards;
}
return _cards;
}
set
{
SetValue(ref _cards, value);
}
}
My remove method
private void RemoveFromCards(Card card)
{
for (int i = Cards.Count - 1; i >= 0; i--)
{
if (Cards[i].Id == card.Id)
{
Cards.RemoveAt(i);
/* I tried this but doesn't work also
*
*
ObservableCollection<Card> copy = Cards;
copy.RemoveAt(i);
Cards = copy;
*/
}
}
}
Calling remove method
private void RemoveCardsFromView(List<Archive> cards)
{
foreach (Archive a in cards)
{
Card c = new Card {Id = a.CardId};
RemoveFromCards(c);
}
}
Calling code
public async Task RefreshCardsView()
{
if (!CrossConnectivity.Current.IsConnected)
{
BuildToast(false,"No internet connection");
return;
}
try
{
JsonResult cards = (JsonResult) await HttpMiddleman.GetCards();
RemoveCardsFromView(cards.Data.DeletedCards);
AddCardsToView(cards.Data.AddedCards);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
BuildToast(false,"Could not refresh");
}
}
My binding in FlowListView
<controls:FlowListView x:Name="Board" HasUnevenRows="True"
BackgroundColor="Black"
FlowColumnCount="2"
FlowItemTappedCommand="{Binding ExecuteActionCommand}"
FlowColumnMinWidth="110"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRefreshing}"
RefreshCommand="{Binding RefreshViewCommand}"
FlowItemsSource="{Binding Cards}"> .....
Thanks in advance guys
make sure that you fire correctly OnPropertyChanged after SetValue() in property statement
and
try with this class (from xamarin) and pass ienumerable of card instead card only object.
Example
private void RemoveFromCards(Card card)
{
Cards.RemoveRange(new []{card});
}
//or directly from
private void RemoveCardsFromView(List<Archive> cards)
{
Cards.RemoveRange(cards.Select(s=> new Card {Id = a.CardId}));
}
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableRangeCollection<T> : ObservableCollection<T>
{
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
/// </summary>
public ObservableRangeCollection()
: base()
{
}
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableRangeCollection(IEnumerable<T> collection)
: base(collection)
{
}
/// <summary>
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
/// </summary>
public void AddRange(IEnumerable<T> collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Add)
{
if (collection == null)
throw new ArgumentNullException("collection");
CheckReentrancy();
if (notificationMode == NotifyCollectionChangedAction.Reset)
{
foreach (var i in collection)
{
Items.Add(i);
}
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return;
}
int startIndex = Count;
var changedItems = collection is List<T> ? (List<T>)collection : new List<T>(collection);
foreach (var i in changedItems)
{
Items.Add(i);
}
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, startIndex));
}
/// <summary>
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
/// </summary>
public void RemoveRange(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
foreach (var i in collection)
Items.Remove(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Clears the current collection and replaces it with the specified item.
/// </summary>
public void Replace(T item)
{
ReplaceRange(new T[] { item });
}
/// <summary>
/// Clears the current collection and replaces it with the specified collection.
/// </summary>
public void ReplaceRange(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
Items.Clear();
AddRange(collection, NotifyCollectionChangedAction.Reset);
}
}
thanks for taking a look at this. I'm new to Unity and struggling to understand how to fix this error.
Assets/Watson/Scripts/Logging/Logger.cs(115,53): error CS0311: The type IBM.Watson.DeveloperCloud.Logging.LogSystem' cannot be used as type parameter T in the generic type or method Singleton. There is no implicit reference conversion from IBM.Watson.DeveloperCloud.Logging.LogSystem' to `UnityEngine.MonoBehaviour
This is the line causing the error:
public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }
And this is it in context:
/// <summary>
/// This singleton class maintains the of list of installed reactors and handles all LogRecord
/// objects. See the static class Log for functions the end user of this system should actually
/// be calling. This class is thread safe.
/// </summary>
public class LogSystem
{
#region Public Properties
/// <summary>
/// Returns the singleton instance of the Logger object.
/// </summary>
**public static LogSystem Instance { get { return Singleton<LogSystem>.Instance; } }**
#endregion
#region Private Data
private static bool sm_bInstalledDefaultReactors = false;
List<ILogReactor> m_Reactors = new List<ILogReactor>();
#endregion
#region Public Functions
public static List<ILogReactor> ReactorsInstalled
{
get
{
return LogSystem.Instance.m_Reactors;
}
}
/// <summary>
/// Install a default debug and file reactor.
/// </summary>
public static void InstallDefaultReactors(int logHistory = 2, LogLevel logLevelFileReactor = LogLevel.STATUS)
{
if (!sm_bInstalledDefaultReactors)
{
// install the default reactors...
sm_bInstalledDefaultReactors = true;
#if UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID
LogSystem.Instance.InstallReactor(new DebugReactor());
#endif
if (!string.IsNullOrEmpty(Constants.Path.LOG_FOLDER) && !System.IO.Directory.Exists(Application.persistentDataPath + Constants.Path.LOG_FOLDER))
System.IO.Directory.CreateDirectory(Application.persistentDataPath + Constants.Path.LOG_FOLDER);
LogSystem.Instance.InstallReactor(new FileReactor(Application.persistentDataPath + Constants.Path.LOG_FOLDER + "/" + Application.productName + ".log", logLevelFileReactor, logHistory));
Application.logMessageReceived += UnityLogCallback;
}
}
static void UnityLogCallback(string condition, string stacktrace, LogType type)
{
if (type == LogType.Exception)
Log.Critical("Unity", "Unity Exception {0} : {1}", condition, stacktrace);
}
/// <summary>
/// Installs a reactor into this Logger.
/// </summary>
/// <param name="reactor">The reactor object.</param>
public void InstallReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
m_Reactors.Add(reactor);
}
// set our default reactor flag to true if the user installs their own reactors.
sm_bInstalledDefaultReactors = true;
}
/// <summary>
/// Removes a reactor from this Logger.
/// </summary>
/// <param name="reactor">The reactor to remove.</param>
/// <returns>Returns true on success.</returns>
public bool RemoveReactor(ILogReactor reactor)
{
lock (m_Reactors)
{
return m_Reactors.Remove(reactor);
}
}
/// <summary>
/// Send the given LogRecord to all installed reactors.
/// </summary>
/// <param name="log">The LogRecord to pass to all reactors.</param>
public void ProcessLog(LogRecord log)
{
lock (m_Reactors)
{
foreach (var reactor in m_Reactors)
reactor.ProcessLog(log);
}
}
#endregion
}
public static LogSystem Instance
{
get
{
return instance;
}
}
private static LogSystem instance;
// Ctor of the class
public LogSystem()
{
if(instance == null) { instance = this;}
}
This is a very basic singleton pattern implementation. You can find more advanced ones online.
I am reading this http://msdn.microsoft.com/en-us/magazine/jj651572.aspx to learn mvvm light framework.
I download the source code Friend.cs.
My question is why some set method of different property are implemented differently.
For example, the setter for First name is, why I need 'ref' keyword for _firstName.
Set(FirstNamePropertyName, ref _firstName, value);
And the setter for DateOfBirthString is "
RaisePropertyChanged(() => DateOfBirth);
When will the linq expression will be evaluated?
namespace MyFriends.Model
{
[SimpleSerialize]
public class Friend : ObservableObject
{
/// <summary>
/// The <see cref="FirstName" /> property's name.
/// </summary>
public const string FirstNamePropertyName = "FirstName";
private string _firstName;
/// <summary>
/// Sets and gets the FirstName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "first_name")]
public string FirstName
{
get
{
return _firstName;
}
set
{
Set(FirstNamePropertyName, ref _firstName, value);
}
}
/// <summary>
/// The <see cref="LastName" /> property's name.
/// </summary>
public const string LastNamePropertyName = "LastName";
private string _lastName;
/// <summary>
/// Sets and gets the LastName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "last_name")]
public string LastName
{
get
{
return _lastName;
}
set
{
Set(LastNamePropertyName, ref _lastName, value);
}
}
/// <summary>
/// The <see cref="DateOfBirth" /> property's name.
/// </summary>
public const string DateOfBirthPropertyName = "DateOfBirth";
private string _dateOfBirthString;
/// <summary>
/// Sets and gets the DateOfBirth property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "birthday")]
public string DateOfBirthString
{
get
{
return _dateOfBirthString;
}
set
{
_dateOfBirthString = value;
RaisePropertyChanged(() => DateOfBirth);
}
}
public DateTime DateOfBirth
{
get
{
if (string.IsNullOrEmpty(_dateOfBirthString))
{
return DateTime.MinValue;
}
return DateTime.ParseExact(DateOfBirthString, "d", CultureInfo.InvariantCulture);
}
set
{
_dateOfBirthString = value.ToString("d", CultureInfo.InvariantCulture);
}
}
private string _imageUrl;
[SimpleSerialize(FieldName = "picture")]
public string ImageUrl
{
get
{
return _imageUrl;
}
set
{
_imageUrl = value;
RaisePropertyChanged(() => ImageUri);
}
}
public Uri ImageUri
{
get
{
return new Uri(_imageUrl);
}
}
}
}
The difference between those two methods is that the Set method replaces the old value of the _firstName field and then raises the PropertyChanged event, while the RaisePropertyChanged only raises the PropertyChanged event.
You'll want to use the Set method in most cases, since it helps to shorten property declarations by wrapping all that typically needs to be done within a property's setter in just one method:
It updates the value of the passed field and overwrites it with the content of value, and then
raises the PropertyChanged event to notify Views about this update.
The reason the field needs to be passed by reference (thus using ref _firstName) is that not the field's content is needed within the Set method, but the field itself is actually updated.
The RaisePropertyChanged method is useful when an update of one property does also affect additional properties. In this case, these properties' contents need to be updated manually, then the RaisePropertyChanged method can be called to inform Views about which properties have actually changed.
One instance I found that Set(ref _prop, value)
doesn't work is when you need to resend an update or need to do a custom comparison. Set(ref _prop, value)
will do a compare on the _prop and value for you but it may not be what you want. For some properties i may want to add some more conditions beyond just a comparison in which case I'll set the _prop = value manually and then raise the change right after;
But in most cases I use the Set(ref _prop, value)
Here is an actual usage, where the IsRunning is the primary operation, but it also raises a change notification on the property IsComplete which is based on IsRunning. This way both properties send a notify without undo extra coding.
private bool _IsRunning;
public bool IsRunning
{
get => _IsRunning;
set
{
SetProperty(ref _IsRunning, value);
RaisePropertyChanged("IsComplete");
}
}
public bool IsComplete => !IsRunning;
How can I be notified when ProgressBar's Value changes with .NET UIAutomation framework? I dont see such property in AutomationElement class.
I drew this sample directly from the MSDN documentation, changing only the property:
AutomationPropertyChangedEventHandler propChangeHandler;
/// <summary>
/// Adds a handler for property-changed event; in particular, a change in the value
/// </summary>
/// <param name="element">The UI Automation element whose state is being monitored.</param>
public void SubscribePropertyChange(AutomationElement element)
{
Automation.AddAutomationPropertyChangedEventHandler(element,
TreeScope.Element,
propChangeHandler = new AutomationPropertyChangedEventHandler(OnPropertyChange),
ValuePattern.ValueProperty);
}
/// <summary>
/// Handler for property changes.
/// </summary>
/// <param name="src">The source whose properties changed.</param>
/// <param name="e">Event arguments.</param>
private void OnPropertyChange(object src, AutomationPropertyChangedEventArgs e)
{
AutomationElement sourceElement = src as AutomationElement;
if (e.Property == ValuePattern.ValueProperty)
{
// TODO: Do something with the new value.
// The element that raised the event can be identified by its runtime ID property.
}
else
{
// TODO: Handle other property-changed events.
}
}
public void UnsubscribePropertyChange(AutomationElement element)
{
if (propChangeHandler != null)
{
Automation.RemoveAutomationPropertyChangedEventHandler(element, propChangeHandler);
}
}